netstack3_ip/
sas.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Provides common SAS (Source Address Selection) implementations.
6
7use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
8use net_types::SpecifiedAddr;
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
15/// A handler for Source Address Selection.
16///
17/// This trait helps implement source address selection for a variety of traits,
18/// like [`crate::IpDeviceStateContext`].
19///
20/// A blanket implementation on IPv4 and IPv6 is provided for all types
21/// implementing [`IpDeviceStateContext`].
22pub trait IpSasHandler<I: IpDeviceIpExt, BT>: IpDeviceAddressIdContext<I> {
23    /// Returns the best local address on `device_id` for communicating with
24    /// `remote`.
25    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    /// Returns a strongly-held reference to the best local address on `device_id`
34    /// for communicating with `remote`.
35    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        // TODO(https://fxbug.dev/42077260) Consider whether the address is
53        // assigned.
54        self.with_address_ids(device_id, |mut addrs, _core_ctx| addrs.next())
55    }
56}
57
58impl<CC, BT> IpSasHandler<Ipv6, BT> for CC
59where
60    CC: IpDeviceStateContext<Ipv6, BT>,
61    BT: IpDeviceStateBindingsTypes,
62{
63    fn get_local_addr_id_for_remote(
64        &mut self,
65        device_id: &Self::DeviceId,
66        remote: Option<SpecifiedAddr<Ipv6Addr>>,
67    ) -> Option<CC::AddressId> {
68        self.with_address_ids(device_id, |addrs, core_ctx| {
69            ipv6_source_address_selection::select_ipv6_source_address(
70                remote,
71                device_id,
72                addrs,
73                |addr_id| {
74                    core_ctx.with_ip_address_data(
75                        device_id,
76                        addr_id,
77                        |IpAddressData { flags: IpAddressFlags { assigned }, config }| {
78                            // Assume an address is deprecated if config is
79                            // not available. That means the address is
80                            // going away, so we should not prefer it.
81                            const ASSUME_DEPRECATED: bool = true;
82                            // Assume an address is not temporary if config
83                            // is not available. That means the address is
84                            // going away and we should remove any
85                            // preference on it.
86                            const ASSUME_TEMPORARY: bool = false;
87                            let (deprecated, temporary) = config
88                                .map(|c| (c.is_deprecated(), c.is_temporary()))
89                                .unwrap_or((ASSUME_DEPRECATED, ASSUME_TEMPORARY));
90                            SasCandidate {
91                                addr_sub: addr_id.addr_sub(),
92                                assigned: *assigned,
93                                temporary,
94                                deprecated,
95                                device: device_id.clone(),
96                            }
97                        },
98                    )
99                },
100            )
101        })
102    }
103}