netlink_packet_route/route/
next_hops.rs
1use 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 Ok(())
66 }
67}
68
69impl<'a, T: AsRef<[u8]> + ?Sized> RouteNextHopBuffer<&'a T> {
70 pub fn attributes(&self) -> impl Iterator<Item = Result<NlaBuffer<&'a [u8]>, NlaError>> {
71 NlasIterator::new(&self.payload()[..(self.length() as usize - PAYLOAD_OFFSET)])
72 }
73}
74
75#[derive(Debug, Clone, Eq, PartialEq, Default)]
76#[non_exhaustive]
77pub struct RouteNextHop {
78 pub flags: RouteNextHopFlags,
80 pub hops: u8,
82 pub interface_index: u32,
84 pub attributes: Vec<RouteAttribute>,
86}
87
88impl<'a, T: AsRef<[u8]>>
89 ParseableParametrized<RouteNextHopBuffer<&'a T>, (AddressFamily, RouteType, RouteLwEnCapType)>
90 for RouteNextHop
91{
92 type Error = RouteError;
93 fn parse_with_param(
94 buf: &RouteNextHopBuffer<&T>,
95 (address_family, route_type, encap_type): (AddressFamily, RouteType, RouteLwEnCapType),
96 ) -> Result<RouteNextHop, RouteError> {
97 let attributes = Vec::<RouteAttribute>::parse_with_param(
98 &RouteNextHopBuffer::new_checked(buf.buffer)?,
99 (address_family, route_type, encap_type),
100 )?;
101 Ok(RouteNextHop {
102 flags: RouteNextHopFlags::from_bits_retain(buf.flags()),
103 hops: buf.hops(),
104 interface_index: buf.interface_index(),
105 attributes,
106 })
107 }
108}
109
110impl<'a, T: AsRef<[u8]> + 'a>
111 ParseableParametrized<RouteNextHopBuffer<&'a T>, (AddressFamily, RouteType, RouteLwEnCapType)>
112 for Vec<RouteAttribute>
113{
114 type Error = RouteError;
115 fn parse_with_param(
116 buf: &RouteNextHopBuffer<&'a T>,
117 (address_family, route_type, encap_type): (AddressFamily, RouteType, RouteLwEnCapType),
118 ) -> Result<Self, RouteError> {
119 let mut nlas = vec![];
120 for nla_buf in buf.attributes() {
121 nlas.push(RouteAttribute::parse_with_param(
122 &nla_buf?,
123 (address_family, route_type, encap_type),
124 )?);
125 }
126 Ok(nlas)
127 }
128}
129
130impl Emitable for RouteNextHop {
131 fn buffer_len(&self) -> usize {
132 PAYLOAD_OFFSET + self.attributes.as_slice().buffer_len()
134 }
135
136 fn emit(&self, buffer: &mut [u8]) {
137 let mut nh_buffer = RouteNextHopBuffer::new(buffer);
138 nh_buffer.set_length(self.buffer_len() as u16);
139 nh_buffer.set_flags(self.flags.bits());
140 nh_buffer.set_hops(self.hops);
141 nh_buffer.set_interface_index(self.interface_index);
142 self.attributes.as_slice().emit(nh_buffer.payload_mut())
143 }
144}