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