netlink_packet_route/neighbour/
attribute.rs

1// SPDX-License-Identifier: MIT
2
3use super::{NeighbourAddress, NeighbourCacheInfo, NeighbourCacheInfoBuffer, NeighbourError};
4use crate::route::RouteProtocol;
5use crate::AddressFamily;
6use byteorder::{BigEndian, ByteOrder, NativeEndian};
7use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
8use netlink_packet_utils::parsers::{parse_u16, parse_u16_be, parse_u32};
9use netlink_packet_utils::{Emitable, Parseable, ParseableParametrized};
10
11const NDA_DST: u16 = 1;
12const NDA_LLADDR: u16 = 2;
13const NDA_CACHEINFO: u16 = 3;
14const NDA_PROBES: u16 = 4;
15const NDA_VLAN: u16 = 5;
16const NDA_PORT: u16 = 6;
17const NDA_VNI: u16 = 7;
18const NDA_IFINDEX: u16 = 8;
19// Kernel constant name is NDA_MASTER
20const NDA_CONTROLLER: u16 = 9;
21const NDA_LINK_NETNSID: u16 = 10;
22const NDA_SRC_VNI: u16 = 11;
23const NDA_PROTOCOL: u16 = 12;
24// const NDA_NH_ID: u16 = 13;
25// const NDA_FDB_EXT_ATTRS: u16 = 14;
26
27#[derive(Debug, PartialEq, Eq, Clone)]
28#[non_exhaustive]
29pub enum NeighbourAttribute {
30    Destination(NeighbourAddress),
31    LinkLocalAddress(Vec<u8>),
32    CacheInfo(NeighbourCacheInfo),
33    Probes(u32),
34    Vlan(u16),
35    Port(u16),
36    Vni(u32),
37    IfIndex(u32),
38    Controller(u32),
39    LinkNetNsId(u32),
40    SourceVni(u32),
41    Protocol(RouteProtocol),
42    Other(DefaultNla),
43}
44
45impl Nla for NeighbourAttribute {
46    fn value_len(&self) -> usize {
47        match self {
48            Self::LinkLocalAddress(bytes) => bytes.len(),
49            Self::Destination(v) => v.buffer_len(),
50            Self::CacheInfo(v) => v.buffer_len(),
51            Self::Vlan(_) | Self::Port(_) => 2,
52            Self::Protocol(v) => v.buffer_len(),
53            Self::Probes(_)
54            | Self::LinkNetNsId(_)
55            | Self::Controller(_)
56            | Self::Vni(_)
57            | Self::IfIndex(_)
58            | Self::SourceVni(_) => 4,
59            Self::Other(attr) => attr.value_len(),
60        }
61    }
62
63    fn emit_value(&self, buffer: &mut [u8]) {
64        match self {
65            Self::Destination(v) => v.emit(buffer),
66            Self::LinkLocalAddress(bytes) => buffer.copy_from_slice(bytes.as_slice()),
67            Self::CacheInfo(v) => v.emit(buffer),
68            Self::Vlan(value) => NativeEndian::write_u16(buffer, *value),
69            Self::Port(value) => BigEndian::write_u16(buffer, *value),
70            Self::Probes(value)
71            | Self::LinkNetNsId(value)
72            | Self::Controller(value)
73            | Self::Vni(value)
74            | Self::IfIndex(value)
75            | Self::SourceVni(value) => NativeEndian::write_u32(buffer, *value),
76            Self::Protocol(v) => v.emit(buffer),
77            Self::Other(attr) => attr.emit_value(buffer),
78        }
79    }
80
81    fn kind(&self) -> u16 {
82        match self {
83            Self::Destination(_) => NDA_DST,
84            Self::LinkLocalAddress(_) => NDA_LLADDR,
85            Self::CacheInfo(_) => NDA_CACHEINFO,
86            Self::Probes(_) => NDA_PROBES,
87            Self::Vlan(_) => NDA_VLAN,
88            Self::Port(_) => NDA_PORT,
89            Self::Vni(_) => NDA_VNI,
90            Self::IfIndex(_) => NDA_IFINDEX,
91            Self::Controller(_) => NDA_CONTROLLER,
92            Self::LinkNetNsId(_) => NDA_LINK_NETNSID,
93            Self::SourceVni(_) => NDA_SRC_VNI,
94            Self::Protocol(_) => NDA_PROTOCOL,
95            Self::Other(nla) => nla.kind(),
96        }
97    }
98}
99
100impl<'a, T: AsRef<[u8]> + ?Sized> ParseableParametrized<NlaBuffer<&'a T>, AddressFamily>
101    for NeighbourAttribute
102{
103    type Error = NeighbourError;
104    fn parse_with_param(
105        buf: &NlaBuffer<&'a T>,
106        address_family: AddressFamily,
107    ) -> Result<Self, Self::Error> {
108        let payload = buf.value();
109        Ok(match buf.kind() {
110            NDA_DST => Self::Destination(
111                NeighbourAddress::parse_with_param(address_family, payload)
112                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_DST", error })?,
113            ),
114            NDA_LLADDR => Self::LinkLocalAddress(payload.to_vec()),
115            NDA_CACHEINFO => Self::CacheInfo(
116                NeighbourCacheInfoBuffer::new_checked(payload)
117                    .and_then(|buffer| NeighbourCacheInfo::parse(&buffer))
118                    .map_err(|error| NeighbourError::InvalidValue {
119                        kind: "NDA_CACHEINFO",
120                        error,
121                    })?,
122            ),
123            NDA_PROBES => Self::Probes(
124                parse_u32(payload)
125                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_PROBES", error })?,
126            ),
127            NDA_VLAN => Self::Vlan(
128                parse_u16(payload)
129                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_VLAN", error })?,
130            ),
131            NDA_PORT => Self::Port(
132                parse_u16_be(payload)
133                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_PORT", error })?,
134            ),
135            NDA_VNI => Self::Vni(
136                parse_u32(payload)
137                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_VNI", error })?,
138            ),
139            NDA_IFINDEX => Self::IfIndex(
140                parse_u32(payload)
141                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_IFINDEX", error })?,
142            ),
143            NDA_CONTROLLER => {
144                Self::Controller(parse_u32(payload).map_err(|error| {
145                    NeighbourError::InvalidValue { kind: "NDA_CONTROLLER", error }
146                })?)
147            }
148            NDA_LINK_NETNSID => Self::LinkNetNsId(parse_u32(payload).map_err(|error| {
149                NeighbourError::InvalidValue { kind: "NDA_LINK_NETNSID", error }
150            })?),
151            NDA_SRC_VNI => Self::SourceVni(
152                parse_u32(payload)
153                    .map_err(|error| NeighbourError::InvalidValue { kind: "NDA_SRC_VNI", error })?,
154            ),
155            NDA_PROTOCOL => Self::Protocol(RouteProtocol::parse(payload)?),
156            kind => Self::Other(
157                DefaultNla::parse(buf)
158                    .map_err(|error| NeighbourError::UnknownNLA { kind, error })?,
159            ),
160        })
161    }
162}