netlink_packet_route/route/
next_hops.rs

1// SPDX-License-Identifier: MIT
2
3use super::super::AddressFamily;
4use super::{RouteAttribute, RouteError, RouteLwEnCapType, RouteType};
5use netlink_packet_utils::nla::{NlaBuffer, NlaError, NlasIterator};
6use netlink_packet_utils::traits::{Emitable, ParseableParametrized};
7use netlink_packet_utils::DecodeError;
8
9pub(crate) const RTNH_F_DEAD: u8 = 1;
10pub(crate) const RTNH_F_PERVASIVE: u8 = 2;
11pub(crate) const RTNH_F_ONLINK: u8 = 4;
12pub(crate) const RTNH_F_OFFLOAD: u8 = 8;
13pub(crate) const RTNH_F_LINKDOWN: u8 = 16;
14pub(crate) const RTNH_F_UNRESOLVED: u8 = 32;
15pub(crate) const RTNH_F_TRAP: u8 = 64;
16
17bitflags! {
18    #[derive(Clone, Eq, PartialEq, Debug, Copy, Default)]
19    #[non_exhaustive]
20    pub struct RouteNextHopFlags: u8 {
21        const Dead = RTNH_F_DEAD;
22        const Pervasive = RTNH_F_PERVASIVE;
23        const Onlink = RTNH_F_ONLINK;
24        const Offload = RTNH_F_OFFLOAD;
25        const Linkdown = RTNH_F_LINKDOWN;
26        const Unresolved = RTNH_F_UNRESOLVED;
27        const Trap = RTNH_F_TRAP;
28        const _ = !0;
29    }
30}
31
32const PAYLOAD_OFFSET: usize = 8;
33
34buffer!(RouteNextHopBuffer {
35    length: (u16, 0..2),
36    flags: (u8, 2),
37    hops: (u8, 3),
38    interface_index: (u32, 4..8),
39    payload: (slice, PAYLOAD_OFFSET..),
40});
41
42impl<T: AsRef<[u8]>> RouteNextHopBuffer<T> {
43    pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
44        let packet = Self::new(buffer);
45        packet.check_buffer_length()?;
46        Ok(packet)
47    }
48
49    fn check_buffer_length(&self) -> Result<(), DecodeError> {
50        let len = self.buffer.as_ref().len();
51        if len < PAYLOAD_OFFSET {
52            return Err(DecodeError::InvalidBufferLength {
53                name: "RouteNextHopBuffer",
54                len,
55                buffer_len: PAYLOAD_OFFSET,
56            });
57        }
58        if len < self.length() as usize {
59            return Err(DecodeError::InvalidBufferLength {
60                name: "RouteNextHopBuffer",
61                len,
62                buffer_len: self.length() as usize,
63            });
64        }
65        if (self.length() as usize) < PAYLOAD_OFFSET {
66            return Err(DecodeError::InvalidBufferLength {
67                name: "RouteNextHopBuffer",
68                len: self.length() as usize,
69                buffer_len: PAYLOAD_OFFSET,
70            });
71        }
72        Ok(())
73    }
74}
75
76impl<'a, T: AsRef<[u8]> + ?Sized> RouteNextHopBuffer<&'a T> {
77    pub fn attributes(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, NlaError>> {
78        NlasIterator::new(&self.payload()[..(self.length() as usize - PAYLOAD_OFFSET)])
79    }
80}
81
82#[derive(Debug, Clone, Eq, PartialEq, Default)]
83#[non_exhaustive]
84pub struct RouteNextHop {
85    /// Next-hop flags
86    pub flags: RouteNextHopFlags,
87    /// Next-hop priority
88    pub hops: u8,
89    /// Interface index for the next-hop
90    pub interface_index: u32,
91    /// Attributes
92    pub attributes: Vec<RouteAttribute>,
93}
94
95impl<'a, T: AsRef<[u8]>>
96    ParseableParametrized<RouteNextHopBuffer<&'a T>, (AddressFamily, RouteType, RouteLwEnCapType)>
97    for RouteNextHop
98{
99    type Error = RouteError;
100    fn parse_with_param(
101        buf: &RouteNextHopBuffer<&T>,
102        (address_family, route_type, encap_type): (AddressFamily, RouteType, RouteLwEnCapType),
103    ) -> Result<RouteNextHop, RouteError> {
104        let attributes = Vec::<RouteAttribute>::parse_with_param(
105            &RouteNextHopBuffer::new_checked(buf.buffer)?,
106            (address_family, route_type, encap_type),
107        )?;
108        Ok(RouteNextHop {
109            flags: RouteNextHopFlags::from_bits_retain(buf.flags()),
110            hops: buf.hops(),
111            interface_index: buf.interface_index(),
112            attributes,
113        })
114    }
115}
116
117impl<'a, T: AsRef<[u8]> + 'a>
118    ParseableParametrized<RouteNextHopBuffer<&'a T>, (AddressFamily, RouteType, RouteLwEnCapType)>
119    for Vec<RouteAttribute>
120{
121    type Error = RouteError;
122    fn parse_with_param(
123        buf: &RouteNextHopBuffer<&'a T>,
124        (address_family, route_type, encap_type): (AddressFamily, RouteType, RouteLwEnCapType),
125    ) -> Result<Self, RouteError> {
126        let mut nlas = vec![];
127        for nla_buf in buf.attributes() {
128            nlas.push(RouteAttribute::parse_with_param(
129                &nla_buf?,
130                (address_family, route_type, encap_type),
131            )?);
132        }
133        Ok(nlas)
134    }
135}
136
137impl Emitable for RouteNextHop {
138    fn buffer_len(&self) -> usize {
139        // len, flags, hops and interface id fields
140        PAYLOAD_OFFSET + self.attributes.as_slice().buffer_len()
141    }
142
143    fn emit(&self, buffer: &mut [u8]) {
144        let mut nh_buffer = RouteNextHopBuffer::new(buffer);
145        nh_buffer.set_length(self.buffer_len() as u16);
146        nh_buffer.set_flags(self.flags.bits());
147        nh_buffer.set_hops(self.hops);
148        nh_buffer.set_interface_index(self.interface_index);
149        self.attributes.as_slice().emit(nh_buffer.payload_mut())
150    }
151}