1use core::fmt::Debug;
9use core::hash::Hash;
10use core::marker::PhantomData;
11use core::num::NonZeroU16;
12
13use derivative::Derivative;
14use net_types::ip::{GenericOverIp, Ip, IpAddress, IpVersion, IpVersionMarker, Ipv4, Ipv6};
15use net_types::{
16 AddrAndZone, MulticastAddress, ScopeableAddress, SpecifiedAddr, Witness, ZonedAddr,
17};
18use thiserror::Error;
19
20use crate::LocalAddressError;
21use crate::data_structures::socketmap::{
22 Entry, IterShadows, OccupiedEntry as SocketMapOccupiedEntry, SocketMap, Tagged,
23};
24use crate::device::{
25 DeviceIdentifier, EitherDeviceId, StrongDeviceIdentifier, WeakDeviceIdentifier,
26};
27use crate::error::{ExistsError, NotFoundError, ZonedAddressError};
28use crate::ip::BroadcastIpExt;
29use crate::socket::SocketCookie;
30use crate::socket::address::{
31 AddrVecIter, ConnAddr, ConnIpAddr, ListenerAddr, ListenerIpAddr, SocketIpAddr,
32};
33use packet_formats::ip::{IpProto, Ipv4Proto, Ipv6Proto};
34
35pub trait DualStackIpExt: Ip {
38 type OtherVersion: DualStackIpExt<OtherVersion = Self>;
40}
41
42impl DualStackIpExt for Ipv4 {
43 type OtherVersion = Ipv6;
44}
45
46impl DualStackIpExt for Ipv6 {
47 type OtherVersion = Ipv4;
48}
49
50pub struct DualStackTuple<I: DualStackIpExt, T: GenericOverIp<I> + GenericOverIp<I::OtherVersion>> {
52 this_stack: <T as GenericOverIp<I>>::Type,
53 other_stack: <T as GenericOverIp<I::OtherVersion>>::Type,
54 _marker: IpVersionMarker<I>,
55}
56
57impl<I: DualStackIpExt, T: GenericOverIp<I> + GenericOverIp<I::OtherVersion>> DualStackTuple<I, T> {
58 pub fn new(this_stack: T, other_stack: <T as GenericOverIp<I::OtherVersion>>::Type) -> Self
60 where
61 T: GenericOverIp<I, Type = T>,
62 {
63 Self { this_stack, other_stack, _marker: IpVersionMarker::new() }
64 }
65
66 pub fn into_inner(
68 self,
69 ) -> (<T as GenericOverIp<I>>::Type, <T as GenericOverIp<I::OtherVersion>>::Type) {
70 let Self { this_stack, other_stack, _marker } = self;
71 (this_stack, other_stack)
72 }
73
74 pub fn into_this_stack(self) -> <T as GenericOverIp<I>>::Type {
76 self.this_stack
77 }
78
79 pub fn this_stack(&self) -> &<T as GenericOverIp<I>>::Type {
81 &self.this_stack
82 }
83
84 pub fn into_other_stack(self) -> <T as GenericOverIp<I::OtherVersion>>::Type {
86 self.other_stack
87 }
88
89 pub fn other_stack(&self) -> &<T as GenericOverIp<I::OtherVersion>>::Type {
91 &self.other_stack
92 }
93
94 pub fn flip(self) -> DualStackTuple<I::OtherVersion, T> {
96 let Self { this_stack, other_stack, _marker } = self;
97 DualStackTuple {
98 this_stack: other_stack,
99 other_stack: this_stack,
100 _marker: IpVersionMarker::new(),
101 }
102 }
103
104 pub fn cast<X>(self) -> DualStackTuple<X, T>
113 where
114 X: DualStackIpExt,
115 T: GenericOverIp<X>
116 + GenericOverIp<X::OtherVersion>
117 + GenericOverIp<Ipv4>
118 + GenericOverIp<Ipv6>,
119 {
120 I::map_ip_in(
121 self,
122 |v4| X::map_ip_out(v4, |t| t, |t| t.flip()),
123 |v6| X::map_ip_out(v6, |t| t.flip(), |t| t),
124 )
125 }
126}
127
128impl<
129 I: DualStackIpExt,
130 NewIp: DualStackIpExt,
131 T: GenericOverIp<NewIp>
132 + GenericOverIp<NewIp::OtherVersion>
133 + GenericOverIp<I>
134 + GenericOverIp<I::OtherVersion>,
135> GenericOverIp<NewIp> for DualStackTuple<I, T>
136{
137 type Type = DualStackTuple<NewIp, T>;
138}
139
140pub trait SocketIpExt: Ip {
142 const LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR: SocketIpAddr<Self::Addr> = unsafe {
144 SocketIpAddr::new_from_specified_unchecked(Self::LOOPBACK_ADDRESS)
147 };
148}
149
150impl<I: Ip> SocketIpExt for I {}
151
152#[cfg(test)]
153mod socket_ip_ext_test {
154 use super::*;
155 use ip_test_macro::ip_test;
156
157 #[ip_test(I)]
158 fn loopback_addr_is_valid_socket_addr<I: SocketIpExt>() {
159 let _addr = SocketIpAddr::new(I::LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR.addr())
164 .expect("loopback address should be a valid SocketIpAddr");
165 }
166}
167
168#[derive(Copy, Clone, Debug, PartialEq, Eq, GenericOverIp)]
170#[generic_over_ip()]
171pub enum EitherIpProto {
172 V4(Ipv4Proto),
174 V6(Ipv6Proto),
176}
177
178impl EitherIpProto {
179 pub fn ip_version(&self) -> IpVersion {
181 match self {
182 Self::V4(_) => IpVersion::V4,
183 Self::V6(_) => IpVersion::V6,
184 }
185 }
186
187 pub fn ip_proto(&self) -> Option<IpProto> {
189 match self {
190 Self::V4(p) => match p {
191 Ipv4Proto::Proto(proto) => Some(*proto),
192 _ => None,
193 },
194 Self::V6(p) => match p {
195 Ipv6Proto::Proto(proto) => Some(*proto),
196 _ => None,
197 },
198 }
199 }
200
201 pub fn u8_value(&self) -> u8 {
203 match self {
204 Self::V4(p) => (*p).into(),
205 Self::V6(p) => (*p).into(),
206 }
207 }
208}
209
210#[derive(Clone, Debug)]
212#[cfg_attr(any(test, feature = "testutils"), derive(PartialEq, Eq))]
213pub struct SocketInfo {
214 pub proto: EitherIpProto,
216 pub cookie: SocketCookie,
218}
219
220#[derive(Debug, PartialEq, Eq)]
228pub enum EitherStack<T, O> {
229 ThisStack(T),
231 OtherStack(O),
233}
234
235impl<T, O> Clone for EitherStack<T, O>
236where
237 T: Clone,
238 O: Clone,
239{
240 #[cfg_attr(feature = "instrumented", track_caller)]
241 fn clone(&self) -> Self {
242 match self {
243 Self::ThisStack(t) => Self::ThisStack(t.clone()),
244 Self::OtherStack(t) => Self::OtherStack(t.clone()),
245 }
246 }
247}
248
249#[derive(Debug)]
266#[allow(missing_docs)]
267pub enum MaybeDualStack<DS, NDS> {
268 DualStack(DS),
269 NotDualStack(NDS),
270}
271
272impl<I: DualStackIpExt, DS: GenericOverIp<I>, NDS: GenericOverIp<I>> GenericOverIp<I>
275 for MaybeDualStack<DS, NDS>
276{
277 type Type = MaybeDualStack<<DS as GenericOverIp<I>>::Type, <NDS as GenericOverIp<I>>::Type>;
278}
279
280#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq, Error)]
282#[generic_over_ip()]
283pub enum SetDualStackEnabledError {
284 #[error("a socket can only have dual stack enabled or disabled while unbound")]
286 SocketIsBound,
287 #[error(transparent)]
289 NotCapable(#[from] NotDualStackCapableError),
290}
291
292#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq, Error)]
295#[generic_over_ip()]
296#[error("socket's protocol is not dual-stack capable")]
297pub struct NotDualStackCapableError;
298
299#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
301pub struct Shutdown {
302 pub send: bool,
306 pub receive: bool,
310}
311
312#[derive(Copy, Clone, Debug, Eq, GenericOverIp, PartialEq)]
314#[generic_over_ip()]
315pub enum ShutdownType {
316 Send,
318 Receive,
320 SendAndReceive,
322}
323
324impl ShutdownType {
325 pub fn to_send_receive(&self) -> (bool, bool) {
327 match self {
328 Self::Send => (true, false),
329 Self::Receive => (false, true),
330 Self::SendAndReceive => (true, true),
331 }
332 }
333
334 pub fn from_send_receive(send: bool, receive: bool) -> Option<Self> {
336 match (send, receive) {
337 (true, false) => Some(Self::Send),
338 (false, true) => Some(Self::Receive),
339 (true, true) => Some(Self::SendAndReceive),
340 (false, false) => None,
341 }
342 }
343}
344
345pub trait SocketIpAddrExt<A: IpAddress>: Witness<A> + ScopeableAddress {
347 fn must_have_zone(&self) -> bool
353 where
354 Self: Copy,
355 {
356 self.try_into_null_zoned().is_some()
357 }
358
359 fn try_into_null_zoned(self) -> Option<AddrAndZone<Self, ()>> {
363 if self.get().is_loopback() {
364 return None;
365 }
366 AddrAndZone::new(self, ())
367 }
368}
369
370impl<A: IpAddress, W: Witness<A> + ScopeableAddress> SocketIpAddrExt<A> for W {}
371
372pub trait SocketZonedAddrExt<W, A, D> {
374 fn resolve_addr_with_device(
382 self,
383 device: Option<D::Weak>,
384 ) -> Result<(W, Option<EitherDeviceId<D, D::Weak>>), ZonedAddressError>
385 where
386 D: StrongDeviceIdentifier;
387}
388
389impl<W, A, D> SocketZonedAddrExt<W, A, D> for ZonedAddr<W, D>
390where
391 W: ScopeableAddress + AsRef<SpecifiedAddr<A>>,
392 A: IpAddress,
393{
394 fn resolve_addr_with_device(
395 self,
396 device: Option<D::Weak>,
397 ) -> Result<(W, Option<EitherDeviceId<D, D::Weak>>), ZonedAddressError>
398 where
399 D: StrongDeviceIdentifier,
400 {
401 let (addr, zone) = self.into_addr_zone();
402 let device = match (zone, device) {
403 (Some(zone), Some(device)) => {
404 if device != zone {
405 return Err(ZonedAddressError::DeviceZoneMismatch);
406 }
407 Some(EitherDeviceId::Strong(zone))
408 }
409 (Some(zone), None) => Some(EitherDeviceId::Strong(zone)),
410 (None, Some(device)) => Some(EitherDeviceId::Weak(device)),
411 (None, None) => {
412 if addr.as_ref().must_have_zone() {
413 return Err(ZonedAddressError::RequiredZoneNotProvided);
414 } else {
415 None
416 }
417 }
418 };
419 Ok((addr, device))
420 }
421}
422
423pub struct SocketDeviceUpdate<'a, A: IpAddress, D: WeakDeviceIdentifier> {
429 pub local_ip: Option<&'a SpecifiedAddr<A>>,
431 pub remote_ip: Option<&'a SpecifiedAddr<A>>,
433 pub old_device: Option<&'a D>,
435}
436
437impl<'a, A: IpAddress, D: WeakDeviceIdentifier> SocketDeviceUpdate<'a, A, D> {
438 pub fn check_update<N>(
441 self,
442 new_device: Option<&N>,
443 ) -> Result<(), SocketDeviceUpdateNotAllowedError>
444 where
445 D: PartialEq<N>,
446 {
447 let Self { local_ip, remote_ip, old_device } = self;
448 let must_have_zone = local_ip.is_some_and(|a| a.must_have_zone())
449 || remote_ip.is_some_and(|a| a.must_have_zone());
450
451 if !must_have_zone {
452 return Ok(());
453 }
454
455 let old_device = old_device.unwrap_or_else(|| {
456 panic!("local_ip={:?} or remote_ip={:?} must have zone", local_ip, remote_ip)
457 });
458
459 if new_device.is_some_and(|new_device| old_device == new_device) {
460 Ok(())
461 } else {
462 Err(SocketDeviceUpdateNotAllowedError)
463 }
464 }
465}
466
467pub struct SocketDeviceUpdateNotAllowedError;
469
470pub trait SocketMapAddrSpec {
475 type LocalIdentifier: Copy + Clone + Debug + Send + Sync + Hash + Eq + Into<NonZeroU16>;
477 type RemoteIdentifier: Copy + Clone + Debug + Send + Sync + Hash + Eq;
479}
480
481pub struct ListenerAddrInfo {
483 pub has_device: bool,
485 pub specified_addr: bool,
488}
489
490impl<A: IpAddress, D: DeviceIdentifier, LI> ListenerAddr<ListenerIpAddr<A, LI>, D> {
491 pub(crate) fn info(&self) -> ListenerAddrInfo {
492 let Self { device, ip: ListenerIpAddr { addr, identifier: _ } } = self;
493 ListenerAddrInfo { has_device: device.is_some(), specified_addr: addr.is_some() }
494 }
495}
496
497pub trait SocketMapStateSpec {
499 type AddrVecTag: Eq + Copy + Debug + 'static;
504
505 fn listener_tag(info: ListenerAddrInfo, state: &Self::ListenerAddrState) -> Self::AddrVecTag;
507
508 fn connected_tag(has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag;
510
511 type ListenerId: Clone + Debug;
513 type ConnId: Clone + Debug;
515
516 type ListenerSharingState: Clone + Debug;
519
520 type ConnSharingState: Clone + Debug;
523
524 type ListenerAddrState: SocketMapAddrStateSpec<Id = Self::ListenerId, SharingState = Self::ListenerSharingState>
526 + Debug;
527
528 type ConnAddrState: SocketMapAddrStateSpec<Id = Self::ConnId, SharingState = Self::ConnSharingState>
530 + Debug;
531}
532
533#[derive(Copy, Clone, Debug, Eq, PartialEq)]
536pub struct IncompatibleError;
537
538pub trait Inserter<T> {
540 fn insert(self, item: T);
545}
546
547impl<'a, T, E: Extend<T>> Inserter<T> for &'a mut E {
548 fn insert(self, item: T) {
549 self.extend([item])
550 }
551}
552
553impl<T> Inserter<T> for ! {
554 fn insert(self, _: T) {
555 match self {}
556 }
557}
558
559pub trait SocketMapAddrStateSpec {
561 type Id;
563
564 type SharingState;
571
572 type Inserter<'a>: Inserter<Self::Id> + 'a
574 where
575 Self: 'a,
576 Self::Id: 'a;
577
578 fn new(new_sharing_state: &Self::SharingState, id: Self::Id) -> Self;
581
582 fn contains_id(&self, id: &Self::Id) -> bool;
584
585 fn try_get_inserter<'a, 'b>(
593 &'b mut self,
594 new_sharing_state: &'a Self::SharingState,
595 ) -> Result<Self::Inserter<'b>, IncompatibleError>;
596
597 fn could_insert(&self, new_sharing_state: &Self::SharingState)
602 -> Result<(), IncompatibleError>;
603
604 fn remove_by_id(&mut self, id: Self::Id) -> RemoveResult;
608
609 fn sharing_state(&self) -> Self::SharingState;
611}
612
613pub trait SocketMapAddrStateUpdateSharingSpec: SocketMapAddrStateSpec {
615 fn try_update_sharing(
618 &mut self,
619 id: Self::Id,
620 new_sharing_state: &Self::SharingState,
621 ) -> Result<(), IncompatibleError>;
622}
623
624pub trait SocketMapConflictPolicy<
626 Addr,
627 SharingState,
628 I: Ip,
629 D: DeviceIdentifier,
630 A: SocketMapAddrSpec,
631>: SocketMapStateSpec
632{
633 fn check_insert_conflicts(
642 new_sharing_state: &SharingState,
643 addr: &Addr,
644 socketmap: &SocketMap<AddrVec<I, D, A>, Bound<Self>>,
645 ) -> Result<(), InsertError>;
646}
647
648pub trait SocketMapUpdateSharingPolicy<Addr, SharingState, I: Ip, D: DeviceIdentifier, A>:
651 SocketMapConflictPolicy<Addr, SharingState, I, D, A>
652where
653 A: SocketMapAddrSpec,
654{
655 fn allows_sharing_update(
658 socketmap: &SocketMap<AddrVec<I, D, A>, Bound<Self>>,
659 addr: &Addr,
660 old_sharing: &SharingState,
661 new_sharing: &SharingState,
662 ) -> Result<(), UpdateSharingError>;
663}
664
665#[derive(Derivative)]
667#[derivative(Debug(bound = "S::ListenerAddrState: Debug, S::ConnAddrState: Debug"))]
668#[allow(missing_docs)]
669pub enum Bound<S: SocketMapStateSpec + ?Sized> {
670 Listen(S::ListenerAddrState),
671 Conn(S::ConnAddrState),
672}
673
674#[derive(Derivative)]
689#[derivative(
690 Debug(bound = "D: Debug"),
691 Clone(bound = "D: Clone"),
692 Eq(bound = "D: Eq"),
693 PartialEq(bound = "D: PartialEq"),
694 Hash(bound = "D: Hash")
695)]
696#[allow(missing_docs)]
697pub enum AddrVec<I: Ip, D, A: SocketMapAddrSpec + ?Sized> {
698 Listen(ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>),
699 Conn(ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>),
700}
701
702impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec + ?Sized>
703 Tagged<AddrVec<I, D, A>> for Bound<S>
704{
705 type Tag = S::AddrVecTag;
706 fn tag(&self, address: &AddrVec<I, D, A>) -> Self::Tag {
707 match (self, address) {
708 (Bound::Listen(l), AddrVec::Listen(addr)) => S::listener_tag(addr.info(), l),
709 (Bound::Conn(c), AddrVec::Conn(ConnAddr { device, ip: _ })) => {
710 S::connected_tag(device.is_some(), c)
711 }
712 (Bound::Listen(_), AddrVec::Conn(_)) => {
713 unreachable!("found listen state for conn addr")
714 }
715 (Bound::Conn(_), AddrVec::Listen(_)) => {
716 unreachable!("found conn state for listen addr")
717 }
718 }
719 }
720}
721
722impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec> IterShadows for AddrVec<I, D, A> {
723 type IterShadows = AddrVecIter<I, D, A>;
724
725 fn iter_shadows(&self) -> Self::IterShadows {
726 let (socket_ip_addr, device) = match self.clone() {
727 AddrVec::Conn(ConnAddr { ip, device }) => (ip.into(), device),
728 AddrVec::Listen(ListenerAddr { ip, device }) => (ip.into(), device),
729 };
730 let mut iter = match device {
731 Some(device) => AddrVecIter::with_device(socket_ip_addr, device),
732 None => AddrVecIter::without_device(socket_ip_addr),
733 };
734 assert_eq!(iter.next().as_ref(), Some(self));
736 iter
737 }
738}
739
740#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
742#[allow(missing_docs)]
743pub enum SocketAddrType {
744 AnyListener,
745 SpecificListener,
746 Connected,
747}
748
749impl<'a, A: IpAddress, LI> From<&'a ListenerIpAddr<A, LI>> for SocketAddrType {
750 fn from(ListenerIpAddr { addr, identifier: _ }: &'a ListenerIpAddr<A, LI>) -> Self {
751 match addr {
752 Some(_) => SocketAddrType::SpecificListener,
753 None => SocketAddrType::AnyListener,
754 }
755 }
756}
757
758impl<'a, A: IpAddress, LI, RI> From<&'a ConnIpAddr<A, LI, RI>> for SocketAddrType {
759 fn from(_: &'a ConnIpAddr<A, LI, RI>) -> Self {
760 SocketAddrType::Connected
761 }
762}
763
764pub enum RemoveResult {
766 Success,
768 IsLast,
771}
772
773#[derive(Derivative)]
774#[derivative(Clone(bound = "S::ListenerId: Clone, S::ConnId: Clone"), Debug(bound = ""))]
775pub enum SocketId<S: SocketMapStateSpec> {
776 Listener(S::ListenerId),
777 Connection(S::ConnId),
778}
779
780#[derive(Derivative)]
794#[derivative(Default(bound = ""))]
795pub struct BoundSocketMap<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
796 addr_to_state: SocketMap<AddrVec<I, D, A>, Bound<S>>,
797}
798
799impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
800 BoundSocketMap<I, D, A, S>
801{
802 pub fn len(&self) -> usize {
804 self.addr_to_state.len()
805 }
806}
807
808pub enum Listener {}
810pub enum Connection {}
812
813pub struct Sockets<AddrToStateMap, SocketType>(AddrToStateMap, PhantomData<SocketType>);
815
816impl<
817 'a,
818 I: Ip,
819 D: DeviceIdentifier,
820 SocketType: ConvertSocketMapState<I, D, A, S>,
821 A: SocketMapAddrSpec,
822 S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
823> Sockets<&'a SocketMap<AddrVec<I, D, A>, Bound<S>>, SocketType>
824{
825 pub fn get_by_addr(self, addr: &SocketType::Addr) -> Option<&'a SocketType::AddrState> {
827 let Self(addr_to_state, _marker) = self;
828 addr_to_state.get(&SocketType::to_addr_vec(addr)).map(|state| {
829 SocketType::from_bound_ref(state)
830 .unwrap_or_else(|| unreachable!("found {:?} for address {:?}", state, addr))
831 })
832 }
833
834 pub fn could_insert(
840 self,
841 addr: &SocketType::Addr,
842 sharing: &SocketType::SharingState,
843 ) -> Result<(), InsertError> {
844 let Self(addr_to_state, _) = self;
845 match self.get_by_addr(addr) {
846 Some(state) => {
847 state.could_insert(sharing).map_err(|IncompatibleError| InsertError::Exists)
848 }
849 None => S::check_insert_conflicts(&sharing, &addr, &addr_to_state),
850 }
851 }
852}
853
854#[derive(Derivative)]
856#[derivative(Debug(bound = ""))]
857pub struct SocketStateEntry<
858 'a,
859 I: Ip,
860 D: DeviceIdentifier,
861 A: SocketMapAddrSpec,
862 S: SocketMapStateSpec,
863 SocketType,
864> {
865 id: SocketId<S>,
866 addr_entry: SocketMapOccupiedEntry<'a, AddrVec<I, D, A>, Bound<S>>,
867 _marker: PhantomData<SocketType>,
868}
869
870impl<
871 'a,
872 I: Ip,
873 D: DeviceIdentifier,
874 SocketType: ConvertSocketMapState<I, D, A, S>,
875 A: SocketMapAddrSpec,
876 S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
877> Sockets<&'a mut SocketMap<AddrVec<I, D, A>, Bound<S>>, SocketType>
878where
879 SocketType::SharingState: Clone,
880 SocketType::Id: Clone,
881{
882 pub fn try_insert(
885 self,
886 socket_addr: SocketType::Addr,
887 tag_state: SocketType::SharingState,
888 id: SocketType::Id,
889 ) -> Result<SocketStateEntry<'a, I, D, A, S, SocketType>, InsertError> {
890 self.try_insert_with(socket_addr, tag_state, |_addr, _sharing| (id, ()))
891 .map(|(entry, ())| entry)
892 }
893
894 pub fn try_insert_with<R>(
899 self,
900 socket_addr: SocketType::Addr,
901 tag_state: SocketType::SharingState,
902 make_id: impl FnOnce(SocketType::Addr, SocketType::SharingState) -> (SocketType::Id, R),
903 ) -> Result<(SocketStateEntry<'a, I, D, A, S, SocketType>, R), InsertError> {
904 let Self(addr_to_state, _) = self;
905 S::check_insert_conflicts(&tag_state, &socket_addr, &addr_to_state)?;
906
907 let addr = SocketType::to_addr_vec(&socket_addr);
908
909 match addr_to_state.entry(addr) {
910 Entry::Occupied(mut o) => {
911 let (id, ret) = o.map_mut(|bound| {
912 let bound = match SocketType::from_bound_mut(bound) {
913 Some(bound) => bound,
914 None => unreachable!("found {:?} for address {:?}", bound, socket_addr),
915 };
916 match <SocketType::AddrState as SocketMapAddrStateSpec>::try_get_inserter(
917 bound, &tag_state,
918 ) {
919 Ok(v) => {
920 let (id, ret) = make_id(socket_addr, tag_state);
921 v.insert(id.clone());
922 Ok((SocketType::to_socket_id(id), ret))
923 }
924 Err(IncompatibleError) => Err(InsertError::Exists),
925 }
926 })?;
927 Ok((SocketStateEntry { id, addr_entry: o, _marker: Default::default() }, ret))
928 }
929 Entry::Vacant(v) => {
930 let (id, ret) = make_id(socket_addr, tag_state.clone());
931 let addr_entry = v.insert(SocketType::to_bound(SocketType::AddrState::new(
932 &tag_state,
933 id.clone(),
934 )));
935 let id = SocketType::to_socket_id(id);
936 Ok((SocketStateEntry { id, addr_entry, _marker: Default::default() }, ret))
937 }
938 }
939 }
940
941 pub fn entry(
943 self,
944 id: &SocketType::Id,
945 addr: &SocketType::Addr,
946 ) -> Option<SocketStateEntry<'a, I, D, A, S, SocketType>> {
947 let Self(addr_to_state, _) = self;
948 let addr_entry = match addr_to_state.entry(SocketType::to_addr_vec(addr)) {
949 Entry::Vacant(_) => return None,
950 Entry::Occupied(o) => o,
951 };
952 let state = SocketType::from_bound_ref(addr_entry.get())?;
953
954 state.contains_id(id).then_some(SocketStateEntry {
955 id: SocketType::to_socket_id(id.clone()),
956 addr_entry,
957 _marker: PhantomData::default(),
958 })
959 }
960
961 pub fn remove(self, id: &SocketType::Id, addr: &SocketType::Addr) -> Result<(), NotFoundError> {
963 self.entry(id, addr)
964 .map(|entry| {
965 entry.remove();
966 })
967 .ok_or(NotFoundError)
968 }
969}
970
971#[derive(Debug)]
974pub struct UpdateSharingError;
975
976impl<
977 'a,
978 I: Ip,
979 D: DeviceIdentifier,
980 SocketType: ConvertSocketMapState<I, D, A, S>,
981 A: SocketMapAddrSpec,
982 S: SocketMapConflictPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
983> SocketStateEntry<'a, I, D, A, S, SocketType>
984where
985 SocketType::Id: Clone,
986{
987 pub fn get_addr(&self) -> &SocketType::Addr {
989 let Self { id: _, addr_entry, _marker } = self;
990 SocketType::from_addr_vec_ref(addr_entry.key())
991 }
992
993 pub fn id(&self) -> &SocketType::Id {
995 let Self { id, addr_entry: _, _marker } = self;
996 SocketType::from_socket_id_ref(id)
997 }
998
999 pub fn try_update_addr(self, new_addr: SocketType::Addr) -> Result<Self, (ExistsError, Self)> {
1001 let Self { id, addr_entry, _marker } = self;
1002
1003 let new_addrvec = SocketType::to_addr_vec(&new_addr);
1004 let old_addr = addr_entry.key().clone();
1005 let (addr_state, addr_to_state) = addr_entry.remove_from_map();
1006 let addr_to_state = match addr_to_state.entry(new_addrvec) {
1007 Entry::Occupied(o) => o.into_map(),
1008 Entry::Vacant(v) => {
1009 let sharing_state = SocketType::from_bound_ref(&addr_state)
1010 .unwrap_or_else(|| {
1011 unreachable!("found {:?} for address {:?}", addr_state, old_addr)
1012 })
1013 .sharing_state();
1014 match S::check_insert_conflicts(&sharing_state, &new_addr, v.get_map()) {
1015 Ok(_) => {
1016 let new_addr_entry = v.insert(addr_state);
1017 return Ok(SocketStateEntry { id, addr_entry: new_addr_entry, _marker });
1018 }
1019 Err(_) => v.into_map(),
1020 }
1021 }
1022 };
1023 let to_restore = addr_state;
1024 let addr_entry = match addr_to_state.entry(old_addr) {
1026 Entry::Occupied(_) => unreachable!("just-removed-from entry is occupied"),
1027 Entry::Vacant(v) => v.insert(to_restore),
1028 };
1029 return Err((ExistsError, SocketStateEntry { id, addr_entry, _marker }));
1030 }
1031
1032 pub fn remove(self) {
1034 let Self { id, mut addr_entry, _marker } = self;
1035 let addr = addr_entry.key().clone();
1036 match addr_entry.map_mut(|value| {
1037 let value = match SocketType::from_bound_mut(value) {
1038 Some(value) => value,
1039 None => unreachable!("found {:?} for address {:?}", value, addr),
1040 };
1041 value.remove_by_id(SocketType::from_socket_id_ref(&id).clone())
1042 }) {
1043 RemoveResult::Success => (),
1044 RemoveResult::IsLast => {
1045 let _: Bound<S> = addr_entry.remove();
1046 }
1047 }
1048 }
1049
1050 pub fn try_update_sharing(
1052 &mut self,
1053 old_sharing_state: &SocketType::SharingState,
1054 new_sharing_state: SocketType::SharingState,
1055 ) -> Result<(), UpdateSharingError>
1056 where
1057 SocketType::AddrState: SocketMapAddrStateUpdateSharingSpec,
1058 S: SocketMapUpdateSharingPolicy<SocketType::Addr, SocketType::SharingState, I, D, A>,
1059 {
1060 let Self { id, addr_entry, _marker } = self;
1061 let addr = SocketType::from_addr_vec_ref(addr_entry.key());
1062
1063 S::allows_sharing_update(
1064 addr_entry.get_map(),
1065 addr,
1066 old_sharing_state,
1067 &new_sharing_state,
1068 )?;
1069
1070 addr_entry
1071 .map_mut(|value| {
1072 let value = match SocketType::from_bound_mut(value) {
1073 Some(value) => value,
1074 None => unreachable!("found invalid state {:?}", value),
1078 };
1079
1080 value.try_update_sharing(
1081 SocketType::from_socket_id_ref(id).clone(),
1082 &new_sharing_state,
1083 )
1084 })
1085 .map_err(|IncompatibleError| UpdateSharingError)
1086 }
1087}
1088
1089impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S> BoundSocketMap<I, D, A, S>
1090where
1091 AddrVec<I, D, A>: IterShadows,
1092 S: SocketMapStateSpec,
1093{
1094 pub fn listeners(&self) -> Sockets<&SocketMap<AddrVec<I, D, A>, Bound<S>>, Listener>
1096 where
1097 S: SocketMapConflictPolicy<
1098 ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1099 <S as SocketMapStateSpec>::ListenerSharingState,
1100 I,
1101 D,
1102 A,
1103 >,
1104 S::ListenerAddrState:
1105 SocketMapAddrStateSpec<Id = S::ListenerId, SharingState = S::ListenerSharingState>,
1106 {
1107 let Self { addr_to_state } = self;
1108 Sockets(addr_to_state, Default::default())
1109 }
1110
1111 pub fn listeners_mut(&mut self) -> Sockets<&mut SocketMap<AddrVec<I, D, A>, Bound<S>>, Listener>
1113 where
1114 S: SocketMapConflictPolicy<
1115 ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1116 <S as SocketMapStateSpec>::ListenerSharingState,
1117 I,
1118 D,
1119 A,
1120 >,
1121 S::ListenerAddrState:
1122 SocketMapAddrStateSpec<Id = S::ListenerId, SharingState = S::ListenerSharingState>,
1123 {
1124 let Self { addr_to_state } = self;
1125 Sockets(addr_to_state, Default::default())
1126 }
1127
1128 pub fn conns(&self) -> Sockets<&SocketMap<AddrVec<I, D, A>, Bound<S>>, Connection>
1130 where
1131 S: SocketMapConflictPolicy<
1132 ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1133 <S as SocketMapStateSpec>::ConnSharingState,
1134 I,
1135 D,
1136 A,
1137 >,
1138 S::ConnAddrState:
1139 SocketMapAddrStateSpec<Id = S::ConnId, SharingState = S::ConnSharingState>,
1140 {
1141 let Self { addr_to_state } = self;
1142 Sockets(addr_to_state, Default::default())
1143 }
1144
1145 pub fn conns_mut(&mut self) -> Sockets<&mut SocketMap<AddrVec<I, D, A>, Bound<S>>, Connection>
1147 where
1148 S: SocketMapConflictPolicy<
1149 ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1150 <S as SocketMapStateSpec>::ConnSharingState,
1151 I,
1152 D,
1153 A,
1154 >,
1155 S::ConnAddrState:
1156 SocketMapAddrStateSpec<Id = S::ConnId, SharingState = S::ConnSharingState>,
1157 {
1158 let Self { addr_to_state } = self;
1159 Sockets(addr_to_state, Default::default())
1160 }
1161
1162 #[cfg(test)]
1163 pub(crate) fn iter_addrs(&self) -> impl Iterator<Item = &AddrVec<I, D, A>> {
1164 let Self { addr_to_state } = self;
1165 addr_to_state.iter().map(|(a, _v): (_, &Bound<S>)| a)
1166 }
1167
1168 pub fn get_shadower_counts(&self, addr: &AddrVec<I, D, A>) -> usize {
1170 let Self { addr_to_state } = self;
1171 addr_to_state.descendant_counts(&addr).map(|(_sharing, size)| size.get()).sum()
1172 }
1173}
1174
1175pub enum FoundSockets<A, It> {
1177 Single(A),
1179 Multicast(It),
1182}
1183
1184#[allow(missing_docs)]
1186#[derive(Debug)]
1187pub enum AddrEntry<'a, I: Ip, D, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
1188 Listen(&'a S::ListenerAddrState, ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>),
1189 Conn(
1190 &'a S::ConnAddrState,
1191 ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1192 ),
1193}
1194
1195impl<I, D, A, S> BoundSocketMap<I, D, A, S>
1196where
1197 I: BroadcastIpExt<Addr: MulticastAddress>,
1198 D: DeviceIdentifier,
1199 A: SocketMapAddrSpec,
1200 S: SocketMapStateSpec
1201 + SocketMapConflictPolicy<
1202 ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>,
1203 <S as SocketMapStateSpec>::ListenerSharingState,
1204 I,
1205 D,
1206 A,
1207 > + SocketMapConflictPolicy<
1208 ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>,
1209 <S as SocketMapStateSpec>::ConnSharingState,
1210 I,
1211 D,
1212 A,
1213 >,
1214{
1215 pub fn lookup_connected(
1221 &self,
1222 (src_ip, src_port): (SocketIpAddr<I::Addr>, A::RemoteIdentifier),
1223 (dst_ip, dst_port): (SocketIpAddr<I::Addr>, A::LocalIdentifier),
1224 device: D,
1225 ) -> Option<&'_ S::ConnAddrState> {
1226 let mut addr = ConnAddr {
1227 ip: ConnIpAddr { local: (dst_ip, dst_port), remote: (src_ip, src_port) },
1228 device: Some(device),
1229 };
1230 let entry = self.conns().get_by_addr(&addr);
1231 if entry.is_some() {
1232 return entry;
1233 }
1234 addr.device = None;
1235 self.conns().get_by_addr(&addr)
1236 }
1237
1238 pub fn iter_receivers(
1244 &self,
1245 (src_ip, src_port): (Option<SocketIpAddr<I::Addr>>, Option<A::RemoteIdentifier>),
1246 (dst_ip, dst_port): (SocketIpAddr<I::Addr>, A::LocalIdentifier),
1247 device: D,
1248 broadcast: Option<I::BroadcastMarker>,
1249 ) -> Option<
1250 FoundSockets<
1251 AddrEntry<'_, I, D, A, S>,
1252 impl Iterator<Item = AddrEntry<'_, I, D, A, S>> + '_,
1253 >,
1254 > {
1255 let mut matching_entries = AddrVecIter::with_device(
1256 match (src_ip, src_port) {
1257 (Some(specified_src_ip), Some(src_port)) => {
1258 ConnIpAddr { local: (dst_ip, dst_port), remote: (specified_src_ip, src_port) }
1259 .into()
1260 }
1261 _ => ListenerIpAddr { addr: Some(dst_ip), identifier: dst_port }.into(),
1262 },
1263 device,
1264 )
1265 .filter_map(move |addr: AddrVec<I, D, A>| match addr {
1266 AddrVec::Listen(l) => {
1267 self.listeners().get_by_addr(&l).map(|state| AddrEntry::Listen(state, l))
1268 }
1269 AddrVec::Conn(c) => self.conns().get_by_addr(&c).map(|state| AddrEntry::Conn(state, c)),
1270 });
1271
1272 if broadcast.is_some() || dst_ip.addr().is_multicast() {
1273 Some(FoundSockets::Multicast(matching_entries))
1274 } else {
1275 let single_entry: Option<_> = matching_entries.next();
1276 single_entry.map(FoundSockets::Single)
1277 }
1278 }
1279}
1280
1281#[derive(Debug, Eq, PartialEq)]
1283pub enum InsertError {
1284 ShadowAddrExists,
1286 Exists,
1288 WouldShadowExisting,
1290 IndirectConflict,
1292}
1293
1294impl From<InsertError> for LocalAddressError {
1295 fn from(value: InsertError) -> Self {
1296 match value {
1297 InsertError::ShadowAddrExists
1298 | InsertError::Exists
1299 | InsertError::IndirectConflict
1300 | InsertError::WouldShadowExisting => LocalAddressError::AddressInUse,
1301 }
1302 }
1303}
1304
1305pub trait ConvertSocketMapState<I: Ip, D, A: SocketMapAddrSpec, S: SocketMapStateSpec> {
1308 type Id;
1309 type SharingState;
1310 type Addr: Debug;
1311 type AddrState: SocketMapAddrStateSpec<Id = Self::Id, SharingState = Self::SharingState>;
1312
1313 fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A>;
1314 fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr;
1315 fn from_bound_ref(bound: &Bound<S>) -> Option<&Self::AddrState>;
1316 fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut Self::AddrState>;
1317 fn to_bound(state: Self::AddrState) -> Bound<S>;
1318 fn to_socket_id(id: Self::Id) -> SocketId<S>;
1319 fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id;
1320}
1321
1322impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
1323 ConvertSocketMapState<I, D, A, S> for Listener
1324{
1325 type Id = S::ListenerId;
1326 type SharingState = S::ListenerSharingState;
1327 type Addr = ListenerAddr<ListenerIpAddr<I::Addr, A::LocalIdentifier>, D>;
1328 type AddrState = S::ListenerAddrState;
1329 fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A> {
1330 AddrVec::Listen(addr.clone())
1331 }
1332
1333 fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr {
1334 match addr {
1335 AddrVec::Listen(l) => l,
1336 AddrVec::Conn(c) => unreachable!("conn addr for listener: {c:?}"),
1337 }
1338 }
1339
1340 fn from_bound_ref(bound: &Bound<S>) -> Option<&S::ListenerAddrState> {
1341 match bound {
1342 Bound::Listen(l) => Some(l),
1343 Bound::Conn(_c) => None,
1344 }
1345 }
1346
1347 fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut S::ListenerAddrState> {
1348 match bound {
1349 Bound::Listen(l) => Some(l),
1350 Bound::Conn(_c) => None,
1351 }
1352 }
1353
1354 fn to_bound(state: S::ListenerAddrState) -> Bound<S> {
1355 Bound::Listen(state)
1356 }
1357 fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id {
1358 match id {
1359 SocketId::Listener(id) => id,
1360 SocketId::Connection(_) => unreachable!("connection ID for listener"),
1361 }
1362 }
1363 fn to_socket_id(id: Self::Id) -> SocketId<S> {
1364 SocketId::Listener(id)
1365 }
1366}
1367
1368impl<I: Ip, D: DeviceIdentifier, A: SocketMapAddrSpec, S: SocketMapStateSpec>
1369 ConvertSocketMapState<I, D, A, S> for Connection
1370{
1371 type Id = S::ConnId;
1372 type SharingState = S::ConnSharingState;
1373 type Addr = ConnAddr<ConnIpAddr<I::Addr, A::LocalIdentifier, A::RemoteIdentifier>, D>;
1374 type AddrState = S::ConnAddrState;
1375 fn to_addr_vec(addr: &Self::Addr) -> AddrVec<I, D, A> {
1376 AddrVec::Conn(addr.clone())
1377 }
1378
1379 fn from_addr_vec_ref(addr: &AddrVec<I, D, A>) -> &Self::Addr {
1380 match addr {
1381 AddrVec::Conn(c) => c,
1382 AddrVec::Listen(l) => unreachable!("listener addr for conn: {l:?}"),
1383 }
1384 }
1385
1386 fn from_bound_ref(bound: &Bound<S>) -> Option<&S::ConnAddrState> {
1387 match bound {
1388 Bound::Listen(_l) => None,
1389 Bound::Conn(c) => Some(c),
1390 }
1391 }
1392
1393 fn from_bound_mut(bound: &mut Bound<S>) -> Option<&mut S::ConnAddrState> {
1394 match bound {
1395 Bound::Listen(_l) => None,
1396 Bound::Conn(c) => Some(c),
1397 }
1398 }
1399
1400 fn to_bound(state: S::ConnAddrState) -> Bound<S> {
1401 Bound::Conn(state)
1402 }
1403
1404 fn from_socket_id_ref(id: &SocketId<S>) -> &Self::Id {
1405 match id {
1406 SocketId::Connection(id) => id,
1407 SocketId::Listener(_) => unreachable!("listener ID for connection"),
1408 }
1409 }
1410 fn to_socket_id(id: Self::Id) -> SocketId<S> {
1411 SocketId::Connection(id)
1412 }
1413}
1414
1415#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
1417pub struct SharingDomain(u64);
1418
1419impl SharingDomain {
1420 pub const fn new(id: u64) -> Self {
1424 SharingDomain(id)
1425 }
1426}
1427
1428#[derive(Default, Debug, Eq, PartialEq, Clone, Copy, Hash)]
1431pub enum ReusePortOption {
1432 #[default]
1434 Disabled,
1435
1436 Enabled(SharingDomain),
1439}
1440
1441impl ReusePortOption {
1442 pub fn is_enabled(&self) -> bool {
1444 matches!(self, ReusePortOption::Enabled(_))
1445 }
1446
1447 pub fn is_shareable_with(&self, other: &Self) -> bool {
1450 match (self, other) {
1451 (ReusePortOption::Enabled(domain1), ReusePortOption::Enabled(domain2)) => {
1452 domain1 == domain2
1453 }
1454 _ => false,
1455 }
1456 }
1457}
1458
1459pub trait SocketDiagnosticsSeed {
1462 type Output;
1464
1465 fn resolve(self) -> Option<Self::Output>;
1467}
1468
1469#[cfg(test)]
1470mod tests {
1471 use alloc::vec;
1472 use alloc::vec::Vec;
1473
1474 use assert_matches::assert_matches;
1475 use net_declare::{net_ip_v4, net_ip_v6};
1476 use net_types::ip::{Ipv4Addr, Ipv6, Ipv6Addr};
1477 use netstack3_hashmap::HashSet;
1478 use test_case::test_case;
1479
1480 use crate::device::testutil::{FakeDeviceId, FakeWeakDeviceId, MultipleDevicesId};
1481 use crate::testutil::set_logger_for_test;
1482
1483 use super::*;
1484
1485 #[test_case(net_ip_v4!("8.8.8.8"))]
1486 #[test_case(net_ip_v4!("127.0.0.1"))]
1487 #[test_case(net_ip_v4!("127.0.8.9"))]
1488 #[test_case(net_ip_v4!("224.1.2.3"))]
1489 fn must_never_have_zone_ipv4(addr: Ipv4Addr) {
1490 let addr = SpecifiedAddr::new(addr).unwrap();
1492 assert_eq!(addr.must_have_zone(), false);
1493 }
1494
1495 #[test_case(net_ip_v6!("1::2:3"), false)]
1496 #[test_case(net_ip_v6!("::1"), false; "localhost")]
1497 #[test_case(net_ip_v6!("1::"), false)]
1498 #[test_case(net_ip_v6!("ff03:1:2:3::1"), false)]
1499 #[test_case(net_ip_v6!("ff02:1:2:3::1"), true)]
1500 #[test_case(Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.get(), true)]
1501 #[test_case(net_ip_v6!("fe80::1"), true)]
1502 fn must_have_zone_ipv6(addr: Ipv6Addr, must_have: bool) {
1503 let addr = SpecifiedAddr::new(addr).unwrap();
1506 assert_eq!(addr.must_have_zone(), must_have);
1507 }
1508
1509 #[test]
1510 fn try_into_null_zoned_ipv6() {
1511 assert_eq!(Ipv6::LOOPBACK_ADDRESS.try_into_null_zoned(), None);
1512 let zoned = Ipv6::ALL_NODES_LINK_LOCAL_MULTICAST_ADDRESS.into_specified();
1513 const ZONE: u32 = 5;
1514 assert_eq!(
1515 zoned.try_into_null_zoned().map(|a| a.map_zone(|()| ZONE)),
1516 Some(AddrAndZone::new(zoned, ZONE).unwrap())
1517 );
1518 }
1519
1520 enum FakeSpec {}
1521
1522 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1523 struct Listener(usize);
1524
1525 #[derive(PartialEq, Eq, Debug, Copy, Clone)]
1526 struct SharingState {
1527 tag: char,
1528 shared: bool,
1529 }
1530
1531 impl SharingState {
1532 fn exclusive(tag: char) -> Self {
1533 Self { tag, shared: false }
1534 }
1535
1536 fn shared(tag: char) -> Self {
1537 Self { tag, shared: true }
1538 }
1539 }
1540
1541 impl SharingState {
1542 fn can_share_with(&self, other: &Self) -> bool {
1543 self.tag == other.tag && self.shared && other.shared
1544 }
1545 }
1546
1547 #[derive(PartialEq, Eq, Debug)]
1548 struct Multiple<T> {
1549 sharing_state: SharingState,
1550 entries: Vec<T>,
1551 }
1552
1553 impl<T> Multiple<T> {
1554 fn new_exclusive(tag: char, entries: Vec<T>) -> Self {
1555 Self { sharing_state: SharingState { tag, shared: false }, entries }
1556 }
1557 }
1558
1559 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1560 struct Conn(usize);
1561
1562 enum FakeAddrSpec {}
1563
1564 impl SocketMapAddrSpec for FakeAddrSpec {
1565 type LocalIdentifier = NonZeroU16;
1566 type RemoteIdentifier = ();
1567 }
1568
1569 impl SocketMapStateSpec for FakeSpec {
1570 type AddrVecTag = SharingState;
1571
1572 type ListenerId = Listener;
1573 type ConnId = Conn;
1574
1575 type ListenerSharingState = SharingState;
1576 type ConnSharingState = SharingState;
1577
1578 type ListenerAddrState = Multiple<Listener>;
1579 type ConnAddrState = Multiple<Conn>;
1580
1581 fn listener_tag(_: ListenerAddrInfo, state: &Self::ListenerAddrState) -> Self::AddrVecTag {
1582 state.sharing_state
1583 }
1584
1585 fn connected_tag(_has_device: bool, state: &Self::ConnAddrState) -> Self::AddrVecTag {
1586 state.sharing_state
1587 }
1588 }
1589
1590 type FakeBoundSocketMap =
1591 BoundSocketMap<Ipv4, FakeWeakDeviceId<FakeDeviceId>, FakeAddrSpec, FakeSpec>;
1592
1593 #[derive(Default)]
1597 struct FakeSocketIdGen {
1598 next_id: usize,
1599 }
1600
1601 impl FakeSocketIdGen {
1602 fn next(&mut self) -> usize {
1603 let next_next_id = self.next_id + 1;
1604 core::mem::replace(&mut self.next_id, next_next_id)
1605 }
1606 }
1607
1608 impl<I: Eq> SocketMapAddrStateSpec for Multiple<I> {
1609 type Id = I;
1610 type SharingState = SharingState;
1611 type Inserter<'a>
1612 = &'a mut Vec<I>
1613 where
1614 I: 'a;
1615
1616 fn new(sharing_state: &SharingState, id: I) -> Self {
1617 Self { sharing_state: *sharing_state, entries: vec![id] }
1618 }
1619
1620 fn contains_id(&self, id: &Self::Id) -> bool {
1621 self.entries.contains(id)
1622 }
1623
1624 fn try_get_inserter<'a, 'b>(
1625 &'b mut self,
1626 new_sharing_state: &'a SharingState,
1627 ) -> Result<Self::Inserter<'b>, IncompatibleError> {
1628 (self.sharing_state == *new_sharing_state)
1629 .then_some(&mut self.entries)
1630 .ok_or(IncompatibleError)
1631 }
1632
1633 fn could_insert(&self, new_sharing_state: &SharingState) -> Result<(), IncompatibleError> {
1634 (self.sharing_state == *new_sharing_state).then_some(()).ok_or(IncompatibleError)
1635 }
1636
1637 fn remove_by_id(&mut self, id: I) -> RemoveResult {
1638 let index = self.entries.iter().position(|i| i == &id).expect("did not find id");
1639 let _: I = self.entries.swap_remove(index);
1640 if self.entries.is_empty() { RemoveResult::IsLast } else { RemoveResult::Success }
1641 }
1642
1643 fn sharing_state(&self) -> Self::SharingState {
1644 self.sharing_state
1645 }
1646 }
1647
1648 impl<D: DeviceIdentifier, A: Into<AddrVec<Ipv4, D, FakeAddrSpec>> + Clone>
1649 SocketMapConflictPolicy<A, SharingState, Ipv4, D, FakeAddrSpec> for FakeSpec
1650 {
1651 fn check_insert_conflicts(
1652 new_sharing_state: &SharingState,
1653 addr: &A,
1654 socketmap: &SocketMap<AddrVec<Ipv4, D, FakeAddrSpec>, Bound<FakeSpec>>,
1655 ) -> Result<(), InsertError> {
1656 let dest: AddrVec<_, _, _> = addr.clone().into();
1657 if dest.iter_shadows().any(|a| {
1658 let entry = socketmap.get(&a);
1659 match entry {
1660 Some(Bound::Listen(Multiple { sharing_state, .. }))
1661 | Some(Bound::Conn(Multiple { sharing_state, .. })) => {
1662 !sharing_state.can_share_with(new_sharing_state)
1663 }
1664 None => false,
1665 }
1666 }) {
1667 return Err(InsertError::ShadowAddrExists);
1668 }
1669
1670 match socketmap.get(&dest) {
1671 Some(Bound::Listen(Multiple { sharing_state, .. }))
1672 | Some(Bound::Conn(Multiple { sharing_state, .. })) => {
1673 if sharing_state != new_sharing_state {
1676 return Err(InsertError::Exists);
1677 }
1678 }
1679 None => (),
1680 }
1681
1682 if socketmap
1683 .descendant_counts(&dest)
1684 .any(|(sharing_state, _count)| !sharing_state.can_share_with(new_sharing_state))
1685 {
1686 Err(InsertError::WouldShadowExisting)
1687 } else {
1688 Ok(())
1689 }
1690 }
1691 }
1692
1693 impl<I: Eq> SocketMapAddrStateUpdateSharingSpec for Multiple<I> {
1694 fn try_update_sharing(
1695 &mut self,
1696 id: Self::Id,
1697 new_sharing_state: &Self::SharingState,
1698 ) -> Result<(), IncompatibleError> {
1699 if self.sharing_state == *new_sharing_state {
1700 return Ok(());
1701 }
1702
1703 if self.entries.len() != 1 {
1708 return Err(IncompatibleError);
1709 }
1710 assert!(self.entries.contains(&id));
1711 self.sharing_state = *new_sharing_state;
1712 Ok(())
1713 }
1714 }
1715
1716 impl<D: DeviceIdentifier, A: Into<AddrVec<Ipv4, D, FakeAddrSpec>> + Clone>
1717 SocketMapUpdateSharingPolicy<A, SharingState, Ipv4, D, FakeAddrSpec> for FakeSpec
1718 {
1719 fn allows_sharing_update(
1720 _socketmap: &SocketMap<AddrVec<Ipv4, D, FakeAddrSpec>, Bound<Self>>,
1721 _addr: &A,
1722 _old_sharing: &SharingState,
1723 _new_sharing_state: &SharingState,
1724 ) -> Result<(), UpdateSharingError> {
1725 Ok(())
1726 }
1727 }
1728
1729 const LISTENER_ADDR: ListenerAddr<
1730 ListenerIpAddr<Ipv4Addr, NonZeroU16>,
1731 FakeWeakDeviceId<FakeDeviceId>,
1732 > = ListenerAddr {
1733 ip: ListenerIpAddr {
1734 addr: Some(unsafe { SocketIpAddr::new_unchecked(net_ip_v4!("1.2.3.4")) }),
1735 identifier: NonZeroU16::new(1).unwrap(),
1736 },
1737 device: None,
1738 };
1739
1740 const CONN_ADDR: ConnAddr<
1741 ConnIpAddr<Ipv4Addr, NonZeroU16, ()>,
1742 FakeWeakDeviceId<FakeDeviceId>,
1743 > = ConnAddr {
1744 ip: ConnIpAddr {
1745 local: (
1746 unsafe { SocketIpAddr::new_unchecked(net_ip_v4!("5.6.7.8")) },
1747 NonZeroU16::new(1).unwrap(),
1748 ),
1749 remote: unsafe { (SocketIpAddr::new_unchecked(net_ip_v4!("8.7.6.5")), ()) },
1750 },
1751 device: None,
1752 };
1753
1754 #[test]
1755 fn bound_insert_get_remove_listener() {
1756 set_logger_for_test();
1757 let mut bound = FakeBoundSocketMap::default();
1758 let mut fake_id_gen = FakeSocketIdGen::default();
1759
1760 let addr = LISTENER_ADDR;
1761
1762 let id = {
1763 let entry = bound
1764 .listeners_mut()
1765 .try_insert(addr, SharingState::exclusive('v'), Listener(fake_id_gen.next()))
1766 .unwrap();
1767 assert_eq!(entry.get_addr(), &addr);
1768 entry.id().clone()
1769 };
1770
1771 assert_eq!(
1772 bound.listeners().get_by_addr(&addr),
1773 Some(&Multiple::new_exclusive('v', vec![id]))
1774 );
1775
1776 assert_eq!(bound.listeners_mut().remove(&id, &addr), Ok(()));
1777 assert_eq!(bound.listeners().get_by_addr(&addr), None);
1778 }
1779
1780 #[test]
1781 fn bound_insert_get_remove_conn() {
1782 set_logger_for_test();
1783 let mut bound = FakeBoundSocketMap::default();
1784 let mut fake_id_gen = FakeSocketIdGen::default();
1785
1786 let addr = CONN_ADDR;
1787
1788 let id = {
1789 let entry = bound
1790 .conns_mut()
1791 .try_insert(addr, SharingState::exclusive('v'), Conn(fake_id_gen.next()))
1792 .unwrap();
1793 assert_eq!(entry.get_addr(), &addr);
1794 entry.id().clone()
1795 };
1796
1797 assert_eq!(bound.conns().get_by_addr(&addr), Some(&Multiple::new_exclusive('v', vec![id])));
1798
1799 assert_eq!(bound.conns_mut().remove(&id, &addr), Ok(()));
1800 assert_eq!(bound.conns().get_by_addr(&addr), None);
1801 }
1802
1803 #[test]
1804 fn bound_iter_addrs() {
1805 set_logger_for_test();
1806 let mut bound = FakeBoundSocketMap::default();
1807 let mut fake_id_gen = FakeSocketIdGen::default();
1808
1809 let listener_addrs = [
1810 (Some(net_ip_v4!("1.1.1.1")), 1),
1811 (Some(net_ip_v4!("2.2.2.2")), 2),
1812 (Some(net_ip_v4!("1.1.1.1")), 3),
1813 (None, 4),
1814 ]
1815 .map(|(ip, identifier)| ListenerAddr {
1816 device: None,
1817 ip: ListenerIpAddr {
1818 addr: ip.map(|x| SocketIpAddr::new(x).unwrap()),
1819 identifier: NonZeroU16::new(identifier).unwrap(),
1820 },
1821 });
1822 let conn_addrs = [
1823 (net_ip_v4!("3.3.3.3"), 3, net_ip_v4!("4.4.4.4")),
1824 (net_ip_v4!("4.4.4.4"), 3, net_ip_v4!("3.3.3.3")),
1825 ]
1826 .map(|(local_ip, local_identifier, remote_ip)| ConnAddr {
1827 ip: ConnIpAddr {
1828 local: (
1829 SocketIpAddr::new(local_ip).unwrap(),
1830 NonZeroU16::new(local_identifier).unwrap(),
1831 ),
1832 remote: (SocketIpAddr::new(remote_ip).unwrap(), ()),
1833 },
1834 device: None,
1835 });
1836
1837 for addr in listener_addrs.iter().cloned() {
1838 let _entry = bound
1839 .listeners_mut()
1840 .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1841 .unwrap();
1842 }
1843 for addr in conn_addrs.iter().cloned() {
1844 let _entry = bound
1845 .conns_mut()
1846 .try_insert(addr, SharingState::exclusive('a'), Conn(fake_id_gen.next()))
1847 .unwrap();
1848 }
1849 let expected_addrs = listener_addrs
1850 .into_iter()
1851 .map(Into::into)
1852 .chain(conn_addrs.into_iter().map(Into::into))
1853 .collect::<HashSet<_>>();
1854
1855 assert_eq!(expected_addrs, bound.iter_addrs().cloned().collect());
1856 }
1857
1858 #[test]
1859 fn try_insert_with_callback_not_called_on_error() {
1860 set_logger_for_test();
1863 let mut bound = FakeBoundSocketMap::default();
1864 let addr = LISTENER_ADDR;
1865
1866 let _: &Listener = bound
1868 .listeners_mut()
1869 .try_insert(addr, SharingState::exclusive('a'), Listener(0))
1870 .unwrap()
1871 .id();
1872
1873 fn is_never_called<A, B, T>(_: A, _: B) -> (T, ()) {
1877 panic!("should never be called");
1878 }
1879
1880 assert_matches!(
1881 bound.listeners_mut().try_insert_with(
1882 addr,
1883 SharingState::exclusive('b'),
1884 is_never_called
1885 ),
1886 Err(InsertError::Exists)
1887 );
1888 assert_matches!(
1889 bound.listeners_mut().try_insert_with(
1890 ListenerAddr { device: Some(FakeWeakDeviceId(FakeDeviceId)), ..addr },
1891 SharingState::exclusive('b'),
1892 is_never_called
1893 ),
1894 Err(InsertError::ShadowAddrExists)
1895 );
1896 assert_matches!(
1897 bound.conns_mut().try_insert_with(
1898 ConnAddr {
1899 device: None,
1900 ip: ConnIpAddr {
1901 local: (addr.ip.addr.unwrap(), addr.ip.identifier),
1902 remote: (SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap(), ()),
1903 },
1904 },
1905 SharingState::exclusive('b'),
1906 is_never_called,
1907 ),
1908 Err(InsertError::ShadowAddrExists)
1909 );
1910 }
1911
1912 #[test]
1913 fn insert_listener_conflict_with_listener() {
1914 set_logger_for_test();
1915 let mut bound = FakeBoundSocketMap::default();
1916 let mut fake_id_gen = FakeSocketIdGen::default();
1917 let addr = LISTENER_ADDR;
1918
1919 let _: &Listener = bound
1920 .listeners_mut()
1921 .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1922 .unwrap()
1923 .id();
1924 assert_matches!(
1925 bound.listeners_mut().try_insert(
1926 addr,
1927 SharingState::exclusive('b'),
1928 Listener(fake_id_gen.next())
1929 ),
1930 Err(InsertError::Exists)
1931 );
1932 }
1933
1934 #[test]
1935 fn insert_listener_conflict_with_shadower() {
1936 set_logger_for_test();
1937 let mut bound = FakeBoundSocketMap::default();
1938 let mut fake_id_gen = FakeSocketIdGen::default();
1939 let addr = LISTENER_ADDR;
1940 let shadows_addr = {
1941 assert_eq!(addr.device, None);
1942 ListenerAddr { device: Some(FakeWeakDeviceId(FakeDeviceId)), ..addr }
1943 };
1944
1945 let _: &Listener = bound
1946 .listeners_mut()
1947 .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1948 .unwrap()
1949 .id();
1950 assert_matches!(
1951 bound.listeners_mut().try_insert(
1952 shadows_addr,
1953 SharingState::exclusive('b'),
1954 Listener(fake_id_gen.next())
1955 ),
1956 Err(InsertError::ShadowAddrExists)
1957 );
1958 }
1959
1960 #[test]
1961 fn insert_conn_conflict_with_listener() {
1962 set_logger_for_test();
1963 let mut bound = FakeBoundSocketMap::default();
1964 let mut fake_id_gen = FakeSocketIdGen::default();
1965 let addr = LISTENER_ADDR;
1966 let shadows_addr = ConnAddr {
1967 device: None,
1968 ip: ConnIpAddr {
1969 local: (addr.ip.addr.unwrap(), addr.ip.identifier),
1970 remote: (SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap(), ()),
1971 },
1972 };
1973
1974 let _: &Listener = bound
1975 .listeners_mut()
1976 .try_insert(addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
1977 .unwrap()
1978 .id();
1979 assert_matches!(
1980 bound.conns_mut().try_insert(
1981 shadows_addr,
1982 SharingState::exclusive('b'),
1983 Conn(fake_id_gen.next())
1984 ),
1985 Err(InsertError::ShadowAddrExists)
1986 );
1987 }
1988
1989 #[test]
1990 fn insert_and_remove_listener() {
1991 set_logger_for_test();
1992 let mut bound = FakeBoundSocketMap::default();
1993 let mut fake_id_gen = FakeSocketIdGen::default();
1994 let addr = LISTENER_ADDR;
1995
1996 let a = bound
1997 .listeners_mut()
1998 .try_insert(addr, SharingState::exclusive('x'), Listener(fake_id_gen.next()))
1999 .unwrap()
2000 .id()
2001 .clone();
2002 let b = bound
2003 .listeners_mut()
2004 .try_insert(addr, SharingState::exclusive('x'), Listener(fake_id_gen.next()))
2005 .unwrap()
2006 .id()
2007 .clone();
2008 assert_ne!(a, b);
2009
2010 assert_eq!(bound.listeners_mut().remove(&a, &addr), Ok(()));
2011 assert_eq!(
2012 bound.listeners().get_by_addr(&addr),
2013 Some(&Multiple::new_exclusive('x', vec![b]))
2014 );
2015 }
2016
2017 #[test]
2018 fn insert_and_remove_conn() {
2019 set_logger_for_test();
2020 let mut bound = FakeBoundSocketMap::default();
2021 let mut fake_id_gen = FakeSocketIdGen::default();
2022 let addr = CONN_ADDR;
2023
2024 let a = bound
2025 .conns_mut()
2026 .try_insert(addr, SharingState::exclusive('x'), Conn(fake_id_gen.next()))
2027 .unwrap()
2028 .id()
2029 .clone();
2030 let b = bound
2031 .conns_mut()
2032 .try_insert(addr, SharingState::exclusive('x'), Conn(fake_id_gen.next()))
2033 .unwrap()
2034 .id()
2035 .clone();
2036 assert_ne!(a, b);
2037
2038 assert_eq!(bound.conns_mut().remove(&a, &addr), Ok(()));
2039 assert_eq!(bound.conns().get_by_addr(&addr), Some(&Multiple::new_exclusive('x', vec![b])));
2040 }
2041
2042 #[test]
2043 fn update_listener_to_shadowed_addr_fails() {
2044 let mut bound = FakeBoundSocketMap::default();
2045 let mut fake_id_gen = FakeSocketIdGen::default();
2046
2047 let first_addr = LISTENER_ADDR;
2048 let second_addr = ListenerAddr {
2049 ip: ListenerIpAddr {
2050 addr: Some(SocketIpAddr::new(net_ip_v4!("1.1.1.1")).unwrap()),
2051 ..LISTENER_ADDR.ip
2052 },
2053 ..LISTENER_ADDR
2054 };
2055 let both_shadow = ListenerAddr {
2056 ip: ListenerIpAddr { addr: None, identifier: first_addr.ip.identifier },
2057 device: None,
2058 };
2059
2060 let first = bound
2061 .listeners_mut()
2062 .try_insert(first_addr, SharingState::exclusive('a'), Listener(fake_id_gen.next()))
2063 .unwrap()
2064 .id()
2065 .clone();
2066 let second = bound
2067 .listeners_mut()
2068 .try_insert(second_addr, SharingState::exclusive('b'), Listener(fake_id_gen.next()))
2069 .unwrap()
2070 .id()
2071 .clone();
2072
2073 let (ExistsError, entry) = bound
2076 .listeners_mut()
2077 .entry(&second, &second_addr)
2078 .unwrap()
2079 .try_update_addr(both_shadow)
2080 .expect_err("update should fail");
2081
2082 assert_eq!(entry.id(), &second);
2084 drop(entry);
2085
2086 let (ExistsError, entry) = bound
2087 .listeners_mut()
2088 .entry(&first, &first_addr)
2089 .unwrap()
2090 .try_update_addr(both_shadow)
2091 .expect_err("update should fail");
2092 assert_eq!(entry.get_addr(), &first_addr);
2093 }
2094
2095 #[test]
2096 fn update_listener_to_conflicting_addr_fails() {
2097 let mut bound = BoundSocketMap::<
2098 Ipv4,
2099 FakeWeakDeviceId<MultipleDevicesId>,
2100 FakeAddrSpec,
2101 FakeSpec,
2102 >::default();
2103 let mut fake_id_gen = FakeSocketIdGen::default();
2104 let device_a_wildcard_addr = ListenerAddr {
2105 ip: ListenerIpAddr { addr: None, identifier: NonZeroU16::new(80).unwrap() },
2106 device: Some(FakeWeakDeviceId(MultipleDevicesId::A)),
2107 };
2108 let device_b_specific_addr = ListenerAddr {
2109 ip: ListenerIpAddr {
2110 addr: Some(SocketIpAddr::new(net_ip_v4!("192.168.1.1")).unwrap()),
2111 identifier: NonZeroU16::new(80).unwrap(),
2112 },
2113 device: Some(FakeWeakDeviceId(MultipleDevicesId::B)),
2114 };
2115 let device_a_specific_addr = ListenerAddr {
2116 ip: ListenerIpAddr {
2117 addr: Some(SocketIpAddr::new(net_ip_v4!("192.168.1.1")).unwrap()),
2118 identifier: NonZeroU16::new(80).unwrap(),
2119 },
2120 device: Some(FakeWeakDeviceId(MultipleDevicesId::A)),
2121 };
2122
2123 let _ = bound
2124 .listeners_mut()
2125 .try_insert(
2126 device_a_wildcard_addr,
2127 SharingState::exclusive('a'),
2128 Listener(fake_id_gen.next()),
2129 )
2130 .expect("binding wildcard listener should succeed");
2131
2132 assert_matches!(
2134 bound.listeners_mut().try_insert(
2135 device_a_specific_addr,
2136 SharingState::exclusive('b'),
2137 Listener(fake_id_gen.next()),
2138 ),
2139 Err(_)
2140 );
2141
2142 let specific_entry = bound
2145 .listeners_mut()
2146 .try_insert(
2147 device_b_specific_addr,
2148 SharingState::exclusive('b'),
2149 Listener(fake_id_gen.next()),
2150 )
2151 .expect("binding dev A specific listener should succeed");
2152
2153 assert_matches!(specific_entry.try_update_addr(device_a_specific_addr), Err(_));
2154 }
2155
2156 #[test]
2157 fn nonexistent_conn_entry() {
2158 let mut map = FakeBoundSocketMap::default();
2159 let mut fake_id_gen = FakeSocketIdGen::default();
2160 let addr = CONN_ADDR;
2161 let conn_id = map
2162 .conns_mut()
2163 .try_insert(addr.clone(), SharingState::exclusive('a'), Conn(fake_id_gen.next()))
2164 .expect("failed to insert")
2165 .id()
2166 .clone();
2167 assert_matches!(map.conns_mut().remove(&conn_id, &addr), Ok(()));
2168
2169 assert!(map.conns_mut().entry(&conn_id, &addr).is_none());
2170 }
2171
2172 #[test]
2173 fn update_conn_sharing() {
2174 let mut map = FakeBoundSocketMap::default();
2175 let mut fake_id_gen = FakeSocketIdGen::default();
2176 let addr = CONN_ADDR;
2177 let mut entry = map
2178 .conns_mut()
2179 .try_insert(addr.clone(), SharingState::exclusive('a'), Conn(fake_id_gen.next()))
2180 .expect("failed to insert");
2181
2182 entry
2183 .try_update_sharing(&SharingState::exclusive('a'), SharingState::exclusive('d'))
2184 .expect("worked");
2185 let mut second_conn = map
2188 .conns_mut()
2189 .try_insert(addr.clone(), SharingState::exclusive('d'), Conn(fake_id_gen.next()))
2190 .expect("can insert");
2191 assert_matches!(
2192 second_conn
2193 .try_update_sharing(&SharingState::exclusive('d'), SharingState::exclusive('e')),
2194 Err(UpdateSharingError)
2195 );
2196 }
2197
2198 #[test]
2199 fn lookup_connected() {
2200 let mut map = FakeBoundSocketMap::default();
2201 let mut fake_id_gen = FakeSocketIdGen::default();
2202
2203 let sharing_state = SharingState::shared('a');
2204
2205 let device_id = FakeWeakDeviceId(FakeDeviceId);
2206 let entry1 = map
2207 .conns_mut()
2208 .try_insert(CONN_ADDR, sharing_state, Conn(fake_id_gen.next()))
2209 .expect("failed to insert")
2210 .id()
2211 .clone();
2212 let conn = map
2213 .lookup_connected(CONN_ADDR.ip.remote, CONN_ADDR.ip.local, device_id)
2214 .expect("lookup should succeed");
2215 assert!(conn.contains_id(&entry1));
2216
2217 let addr_with_device = ConnAddr { device: Some(device_id), ..CONN_ADDR };
2220 let entry2 = map
2221 .conns_mut()
2222 .try_insert(addr_with_device, sharing_state, Conn(fake_id_gen.next()))
2223 .expect("failed to insert")
2224 .id()
2225 .clone();
2226 let conn = map
2227 .lookup_connected(CONN_ADDR.ip.remote, CONN_ADDR.ip.local, device_id)
2228 .expect("lookup should succeed");
2229 assert!(conn.contains_id(&entry2));
2230 }
2231}