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