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