Skip to main content

netlink_packet_route/route/
message.rs

1// SPDX-License-Identifier: MIT
2
3use super::super::AddressFamily;
4use super::attribute::RTA_ENCAP_TYPE;
5use super::error::RouteError;
6use super::{RouteAttribute, RouteHeader, RouteLwEnCapType, RouteMessageBuffer, RouteType};
7use crate::RouteNetlinkMessageParseMode;
8use netlink_packet_utils::nla::{HasNlas, NlaParseMode};
9use netlink_packet_utils::traits::{Emitable, Parseable, ParseableParametrized};
10
11#[derive(Debug, PartialEq, Eq, Clone, Default)]
12#[non_exhaustive]
13pub struct RouteMessage {
14    pub header: RouteHeader,
15    pub attributes: Vec<RouteAttribute>,
16}
17
18impl Emitable for RouteMessage {
19    fn buffer_len(&self) -> usize {
20        self.header.buffer_len() + self.attributes.as_slice().buffer_len()
21    }
22
23    fn emit(&self, buffer: &mut [u8]) {
24        self.header.emit(buffer);
25        self.attributes.as_slice().emit(&mut buffer[self.header.buffer_len()..]);
26    }
27}
28
29impl<'a, T: AsRef<[u8]> + 'a>
30    ParseableParametrized<RouteMessageBuffer<&'a T>, RouteNetlinkMessageParseMode>
31    for RouteMessage
32{
33    type Error = RouteError;
34    fn parse_with_param(
35        buf: &RouteMessageBuffer<&'a T>,
36        mode: RouteNetlinkMessageParseMode,
37    ) -> Result<Self, RouteError> {
38        // unwrap: RouteHeader can't fail.
39        let header = RouteHeader::parse(buf).unwrap();
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                (mode.into(), address_family, route_type),
47            )?,
48        })
49    }
50}
51
52impl<'a, T: AsRef<[u8]> + 'a>
53    ParseableParametrized<RouteMessageBuffer<&'a T>, (NlaParseMode, AddressFamily, RouteType)>
54    for Vec<RouteAttribute>
55{
56    type Error = RouteError;
57    fn parse_with_param(
58        buf: &RouteMessageBuffer<&'a T>,
59        (mode, address_family, route_type): (NlaParseMode, AddressFamily, RouteType),
60    ) -> Result<Self, RouteError> {
61        let mut encap_type = RouteLwEnCapType::None;
62        // The RTA_ENCAP_TYPE is provided __after__ RTA_ENCAP, we should find
63        // RTA_ENCAP_TYPE first.
64        for nla_buf in buf.attributes() {
65            let nla = match nla_buf {
66                Ok(n) => n,
67                Err(_) => continue,
68            };
69            if nla.kind() == RTA_ENCAP_TYPE {
70                if let Ok(RouteAttribute::EncapType(v)) =
71                    RouteAttribute::parse_with_param(&nla, (address_family, route_type, encap_type))
72                {
73                    encap_type = v;
74                    break;
75                }
76            }
77        }
78        buf.parse_attributes(mode, |b| {
79            RouteAttribute::parse_with_param(b, (address_family, route_type, encap_type))
80        })
81    }
82}