blob: 4f5bd5869faa499c52fd0917eeecefe6c47b5848 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! The integrations for protocols built on top of IP.
use lock_order::{relation::LockBefore, wrap::prelude::*};
use net_types::{
ip::{Ip, Ipv4, Ipv6},
MulticastAddr,
};
use crate::{
ip::{
device::{self, IpDeviceBindingsContext, IpDeviceIpExt},
path_mtu::{PmtuCache, PmtuContext},
reassembly::{FragmentContext, IpPacketFragmentCache},
IpLayerBindingsContext, IpLayerContext, IpLayerIpExt, MulticastMembershipHandler,
ResolveRouteError,
},
routes::ResolvedRoute,
socket::address::SocketIpAddr,
BindingsContext, BindingsTypes, CoreCtx,
};
impl<I, BT, L> FragmentContext<I, BT> for CoreCtx<'_, BT, L>
where
I: IpLayerIpExt,
BT: BindingsTypes,
L: LockBefore<crate::lock_ordering::IpStateFragmentCache<I>>,
{
fn with_state_mut<O, F: FnOnce(&mut IpPacketFragmentCache<I, BT>) -> O>(&mut self, cb: F) -> O {
let mut cache = self.lock::<crate::lock_ordering::IpStateFragmentCache<I>>();
cb(&mut cache)
}
}
impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpStatePmtuCache<Ipv4>>>
PmtuContext<Ipv4, BC> for CoreCtx<'_, BC, L>
{
fn with_state_mut<O, F: FnOnce(&mut PmtuCache<Ipv4, BC>) -> O>(&mut self, cb: F) -> O {
let mut cache = self.lock::<crate::lock_ordering::IpStatePmtuCache<Ipv4>>();
cb(&mut cache)
}
}
impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpStatePmtuCache<Ipv6>>>
PmtuContext<Ipv6, BC> for CoreCtx<'_, BC, L>
{
fn with_state_mut<O, F: FnOnce(&mut PmtuCache<Ipv6, BC>) -> O>(&mut self, cb: F) -> O {
let mut cache = self.lock::<crate::lock_ordering::IpStatePmtuCache<Ipv6>>();
cb(&mut cache)
}
}
impl<
I: Ip + IpDeviceIpExt + IpLayerIpExt,
BC: BindingsContext
+ IpDeviceBindingsContext<I, Self::DeviceId>
+ IpLayerBindingsContext<I, Self::DeviceId>,
L: LockBefore<crate::lock_ordering::IpState<I>>,
> MulticastMembershipHandler<I, BC> for CoreCtx<'_, BC, L>
where
Self: device::IpDeviceConfigurationContext<I, BC> + IpLayerContext<I, BC>,
{
fn join_multicast_group(
&mut self,
bindings_ctx: &mut BC,
device: &Self::DeviceId,
addr: MulticastAddr<I::Addr>,
) {
crate::ip::device::join_ip_multicast::<I, _, _>(self, bindings_ctx, device, addr)
}
fn leave_multicast_group(
&mut self,
bindings_ctx: &mut BC,
device: &Self::DeviceId,
addr: MulticastAddr<I::Addr>,
) {
crate::ip::device::leave_ip_multicast::<I, _, _>(self, bindings_ctx, device, addr)
}
fn select_device_for_multicast_group(
&mut self,
addr: MulticastAddr<I::Addr>,
) -> Result<Self::DeviceId, ResolveRouteError> {
let remote_ip = SocketIpAddr::new_from_multicast(addr);
let ResolvedRoute { src_addr: _, device, local_delivery_device, next_hop: _ } =
crate::ip::resolve_route_to_destination(self, None, None, Some(remote_ip))?;
// NB: Because the original address is multicast, it cannot be assigned
// to a local interface. Thus local delivery should never be requested.
debug_assert!(local_delivery_device.is_none(), "{:?}", local_delivery_device);
Ok(device)
}
}