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