netstack3_ip/raw/
state.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//! Declares types and functionality related to the state of raw IP sockets.
6
7use derivative::Derivative;
8use lock_order::lock::{OrderedLockAccess, OrderedLockRef};
9use netstack3_base::sync::RwLock;
10use netstack3_base::{IpExt, Marks, WeakDeviceIdentifier};
11
12use crate::internal::raw::counters::RawIpSocketCounters;
13use crate::internal::raw::filter::RawIpSocketIcmpFilter;
14use crate::internal::raw::protocol::RawIpSocketProtocol;
15use crate::internal::raw::RawIpSocketsBindingsTypes;
16use crate::internal::socket::SocketHopLimits;
17
18/// State for a raw IP socket that can be modified, and is lock protected.
19#[derive(Derivative)]
20#[derivative(Default(bound = ""))]
21pub struct RawIpSocketLockedState<I: IpExt, D: WeakDeviceIdentifier> {
22    /// The socket's bound device. When set, the socket will only be able to
23    /// send/receive packets via this device.
24    ///
25    /// Held as a weak identifier, because binding a socket to a device should
26    /// not obstruct removal of the device.
27    pub(crate) bound_device: Option<D>,
28    /// The socket's ICMP filters. When set, all received ICMP packets will need
29    /// to pass the filter, in order to be delivered to the socket.
30    pub(crate) icmp_filter: Option<RawIpSocketIcmpFilter<I>>,
31    /// The socket's hop limits.
32    pub(crate) hop_limits: SocketHopLimits<I>,
33    /// Whether the socket should loop back sent multicast traffic.
34    #[derivative(Default(value = "true"))]
35    pub(crate) multicast_loop: bool,
36    /// The sockets' marks.
37    pub(crate) marks: Marks,
38    /// Whether the system should generate/validate checksums for packets
39    /// sent/received by this socket.
40    // TODO(https://fxbug.dev/343672830): Support enabling/disabling checksum
41    // support on IPv6 sockets. At the moment this is statically determined by
42    // the socket's protocol.
43    pub(crate) system_checksums: bool,
44}
45
46/// State held by a raw IP socket.
47pub struct RawIpSocketState<I: IpExt, D: WeakDeviceIdentifier, BT: RawIpSocketsBindingsTypes> {
48    /// The bindings state associated with this socket.
49    external_state: BT::RawIpSocketState<I>,
50    /// The IANA Internet Protocol of this socket.
51    ///
52    /// This field is specified at creation time and never changes.
53    protocol: RawIpSocketProtocol<I>,
54    /// The locked socket state, accessible via the [`RawIpSocketStateContext`].
55    locked_state: RwLock<RawIpSocketLockedState<I, D>>,
56    /// The counters for this socket.
57    counters: RawIpSocketCounters<I>,
58}
59
60impl<I: IpExt, D: WeakDeviceIdentifier, BT: RawIpSocketsBindingsTypes> RawIpSocketState<I, D, BT> {
61    pub(super) fn new(
62        protocol: RawIpSocketProtocol<I>,
63        external_state: BT::RawIpSocketState<I>,
64    ) -> RawIpSocketState<I, D, BT> {
65        RawIpSocketState {
66            external_state,
67            protocol,
68            locked_state: Default::default(),
69            counters: Default::default(),
70        }
71    }
72    pub(super) fn protocol(&self) -> &RawIpSocketProtocol<I> {
73        &self.protocol
74    }
75    pub(super) fn external_state(&self) -> &BT::RawIpSocketState<I> {
76        &self.external_state
77    }
78    pub(super) fn into_external_state(self) -> BT::RawIpSocketState<I> {
79        let RawIpSocketState { protocol: _, locked_state: _, counters: _, external_state } = self;
80        external_state
81    }
82
83    /// Get the counters for this socket.
84    pub fn counters(&self) -> &RawIpSocketCounters<I> {
85        &self.counters
86    }
87
88    /// Helper function to circumvent lock ordering, for tests.
89    #[cfg(test)]
90    pub(super) fn locked_state(&self) -> &RwLock<RawIpSocketLockedState<I, D>> {
91        &self.locked_state
92    }
93}
94
95impl<I: IpExt, D: WeakDeviceIdentifier, BT: RawIpSocketsBindingsTypes>
96    OrderedLockAccess<RawIpSocketLockedState<I, D>> for RawIpSocketState<I, D, BT>
97{
98    type Lock = RwLock<RawIpSocketLockedState<I, D>>;
99
100    fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
101        OrderedLockRef::new(&self.locked_state)
102    }
103}