netlink_packet_route/route/
message.rs1use netlink_packet_core::{
4 DecodeError, Emitable, ErrorContext, Parseable, ParseableParametrized,
5};
6
7use super::{
8 super::AddressFamily, attribute::RTA_ENCAP_TYPE, RouteAttribute,
9 RouteHeader, RouteLwEnCapType, RouteMessageBuffer, RouteType,
10};
11
12#[derive(Debug, PartialEq, Eq, Clone, Default)]
13#[non_exhaustive]
14pub struct RouteMessage {
15 pub header: RouteHeader,
16 pub attributes: Vec<RouteAttribute>,
17}
18
19impl Emitable for RouteMessage {
20 fn buffer_len(&self) -> usize {
21 self.header.buffer_len() + self.attributes.as_slice().buffer_len()
22 }
23
24 fn emit(&self, buffer: &mut [u8]) {
25 self.header.emit(buffer);
26 self.attributes
27 .as_slice()
28 .emit(&mut buffer[self.header.buffer_len()..]);
29 }
30}
31
32impl<'a, T: AsRef<[u8]> + 'a> Parseable<RouteMessageBuffer<&'a T>>
33 for RouteMessage
34{
35 fn parse(buf: &RouteMessageBuffer<&'a T>) -> Result<Self, DecodeError> {
36 let header = RouteHeader::parse(buf)
37 .context("failed to parse route message header")?;
38 let address_family = header.address_family;
39 let route_type = header.kind;
40 Ok(RouteMessage {
41 header,
42 attributes: Vec::<RouteAttribute>::parse_with_param(
43 buf,
44 (address_family, route_type),
45 )
46 .context("failed to parse route message NLAs")?,
47 })
48 }
49}
50
51impl<'a, T: AsRef<[u8]> + 'a>
52 ParseableParametrized<RouteMessageBuffer<&'a T>, (AddressFamily, RouteType)>
53 for Vec<RouteAttribute>
54{
55 fn parse_with_param(
56 buf: &RouteMessageBuffer<&'a T>,
57 (address_family, route_type): (AddressFamily, RouteType),
58 ) -> Result<Self, DecodeError> {
59 let mut attributes = vec![];
60 let mut encap_type = RouteLwEnCapType::None;
61 for nla_buf in buf.attributes() {
64 let nla = match nla_buf {
65 Ok(n) => n,
66 Err(_) => continue,
67 };
68 if nla.kind() == RTA_ENCAP_TYPE {
69 if let Ok(RouteAttribute::EncapType(v)) =
70 RouteAttribute::parse_with_param(
71 &nla,
72 (address_family, route_type, encap_type),
73 )
74 {
75 encap_type = v;
76 break;
77 }
78 }
79 }
80 for nla_buf in buf.attributes() {
81 attributes.push(RouteAttribute::parse_with_param(
82 &nla_buf?,
83 (address_family, route_type, encap_type),
84 )?);
85 }
86 Ok(attributes)
87 }
88}