1use net_types::SpecifiedAddr;
8use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
9use netstack3_base::{IpAddressId, IpDeviceAddr, IpDeviceAddressIdContext};
10
11use crate::internal::device::state::{IpAddressData, IpAddressFlags, IpDeviceStateBindingsTypes};
12use crate::internal::device::{IpDeviceAddressContext as _, IpDeviceIpExt, IpDeviceStateContext};
13use crate::internal::socket::ipv6_source_address_selection::{self, SasCandidate};
14
15pub trait IpSasHandler<I: IpDeviceIpExt, BT>: IpDeviceAddressIdContext<I> {
23 fn get_local_addr_for_remote(
26 &mut self,
27 device_id: &Self::DeviceId,
28 remote: Option<SpecifiedAddr<I::Addr>>,
29 ) -> Option<IpDeviceAddr<I::Addr>> {
30 self.get_local_addr_id_for_remote(device_id, remote).map(|id| id.addr())
31 }
32
33 fn get_local_addr_id_for_remote(
36 &mut self,
37 device_id: &Self::DeviceId,
38 remote: Option<SpecifiedAddr<I::Addr>>,
39 ) -> Option<Self::AddressId>;
40}
41
42impl<CC, BT> IpSasHandler<Ipv4, BT> for CC
43where
44 CC: IpDeviceStateContext<Ipv4, BT>,
45 BT: IpDeviceStateBindingsTypes,
46{
47 fn get_local_addr_id_for_remote(
48 &mut self,
49 device_id: &Self::DeviceId,
50 _remote: Option<SpecifiedAddr<Ipv4Addr>>,
51 ) -> Option<CC::AddressId> {
52 self.with_address_ids(device_id, |addrs, core_ctx| {
53 addrs
56 .filter(|addr_id| {
57 core_ctx.with_ip_address_data(
58 device_id,
59 addr_id,
60 |IpAddressData { flags: IpAddressFlags { assigned }, config: _ }| *assigned,
61 )
62 })
63 .next()
65 })
66 }
67}
68
69impl<CC, BT> IpSasHandler<Ipv6, BT> for CC
70where
71 CC: IpDeviceStateContext<Ipv6, BT>,
72 BT: IpDeviceStateBindingsTypes,
73{
74 fn get_local_addr_id_for_remote(
75 &mut self,
76 device_id: &Self::DeviceId,
77 remote: Option<SpecifiedAddr<Ipv6Addr>>,
78 ) -> Option<CC::AddressId> {
79 self.with_address_ids(device_id, |addrs, core_ctx| {
80 ipv6_source_address_selection::select_ipv6_source_address(
81 remote,
82 device_id,
83 addrs,
84 |addr_id| {
85 core_ctx.with_ip_address_data(
86 device_id,
87 addr_id,
88 |IpAddressData { flags: IpAddressFlags { assigned }, config }| {
89 const ASSUME_DEPRECATED: bool = true;
93 const ASSUME_TEMPORARY: bool = false;
98 let (deprecated, temporary) = config
99 .map(|c| (c.is_deprecated(), c.is_temporary()))
100 .unwrap_or((ASSUME_DEPRECATED, ASSUME_TEMPORARY));
101 SasCandidate {
102 addr_sub: addr_id.addr_sub(),
103 assigned: *assigned,
104 temporary,
105 deprecated,
106 device: device_id.clone(),
107 }
108 },
109 )
110 },
111 )
112 })
113 }
114}