netlink_packet_route/link/af_spec/
bridge.rs1use netlink_packet_core::{
4 emit_u16, emit_u32, parse_u16, parse_u32, DecodeError, DefaultNla,
5 Emitable, ErrorContext, Nla, NlaBuffer, NlasIterator, Parseable,
6};
7
8const IFLA_BRIDGE_FLAGS: u16 = 0;
9const IFLA_BRIDGE_MODE: u16 = 1;
10const IFLA_BRIDGE_VLAN_INFO: u16 = 2;
11const IFLA_BRIDGE_VLAN_TUNNEL_INFO: u16 = 3;
12#[derive(Clone, Eq, PartialEq, Debug)]
17#[non_exhaustive]
18pub enum AfSpecBridge {
19 Flags(BridgeFlag),
20 Mode(BridgeMode),
21 VlanInfo(BridgeVlanInfo),
22 VlanTunnelInfo(Vec<BridgeVlanTunnelInfo>),
23 Other(DefaultNla),
24}
25
26impl Nla for AfSpecBridge {
27 fn value_len(&self) -> usize {
28 match self {
29 Self::Flags(_) => BridgeFlag::LENGTH,
30 Self::Mode(_) => BridgeMode::LENGTH,
31 Self::VlanInfo(_) => BridgeVlanInfo::LENGTH,
32 Self::VlanTunnelInfo(s) => s.as_slice().buffer_len(),
33 Self::Other(nla) => nla.value_len(),
34 }
35 }
36
37 fn emit_value(&self, buffer: &mut [u8]) {
38 match self {
39 Self::Flags(value) => emit_u16(buffer, u16::from(*value)).unwrap(),
40 Self::Mode(value) => emit_u16(buffer, u16::from(*value)).unwrap(),
41 Self::VlanInfo(info) => {
42 buffer[..4].copy_from_slice(<[u8; 4]>::from(info).as_slice())
43 }
44 Self::VlanTunnelInfo(s) => s.as_slice().emit(buffer),
45 Self::Other(nla) => nla.emit_value(buffer),
46 }
47 }
48
49 fn kind(&self) -> u16 {
50 match self {
51 Self::Flags(_) => IFLA_BRIDGE_FLAGS,
52 Self::Mode(_) => IFLA_BRIDGE_MODE,
53 Self::VlanInfo(_) => IFLA_BRIDGE_VLAN_INFO,
54 Self::VlanTunnelInfo(_) => IFLA_BRIDGE_VLAN_TUNNEL_INFO,
55 Self::Other(nla) => nla.kind(),
56 }
57 }
58}
59
60impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for AfSpecBridge {
61 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
62 let payload = buf.value();
63 Ok(match buf.kind() {
64 IFLA_BRIDGE_FLAGS => Self::Flags(
65 parse_u16(payload)
66 .context("Invalid IFLA_BRIDGE_FLAGS value")?
67 .into(),
68 ),
69 IFLA_BRIDGE_MODE => Self::Mode(
70 parse_u16(payload)
71 .context("Invalid IFLA_BRIDGE_MODE value")?
72 .into(),
73 ),
74 IFLA_BRIDGE_VLAN_INFO => Self::VlanInfo(
75 BridgeVlanInfo::try_from(payload)
76 .context("Invalid IFLA_BRIDGE_VLAN_INFO value")?,
77 ),
78 IFLA_BRIDGE_VLAN_TUNNEL_INFO => {
79 let mut nlas = Vec::new();
80 for nla in NlasIterator::new(payload) {
81 let nla = &nla.context(format!(
82 "Invalid IFLA_BRIDGE_VLAN_TUNNEL_INFO for {payload:?}"
83 ))?;
84 let parsed = BridgeVlanTunnelInfo::parse(nla)?;
85 nlas.push(parsed);
86 }
87 Self::VlanTunnelInfo(nlas)
88 }
89 kind => Self::Other(
90 DefaultNla::parse(buf)
91 .context(format!("Unknown NLA type {kind}"))?,
92 ),
93 })
94 }
95}
96
97#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "android"))]
98pub(crate) struct VecAfSpecBridge(pub(crate) Vec<AfSpecBridge>);
99
100#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "android"))]
101impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
102 for VecAfSpecBridge
103{
104 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
105 let mut nlas = vec![];
106 let err = "Invalid AF_INET NLA for IFLA_AF_SPEC(AF_BRIDGE)";
107 for nla in NlasIterator::new(buf.into_inner()) {
108 let nla = nla.context(err)?;
109 nlas.push(AfSpecBridge::parse(&nla).context(err)?);
110 }
111 Ok(Self(nlas))
112 }
113}
114
115const BRIDGE_VLAN_INFO_CONTROLLER: u16 = 1 << 0;
116const BRIDGE_VLAN_INFO_PVID: u16 = 1 << 1;
117const BRIDGE_VLAN_INFO_UNTAGGED: u16 = 1 << 2;
118const BRIDGE_VLAN_INFO_RANGE_BEGIN: u16 = 1 << 3;
119const BRIDGE_VLAN_INFO_RANGE_END: u16 = 1 << 4;
120const BRIDGE_VLAN_INFO_BRENTRY: u16 = 1 << 5;
121const BRIDGE_VLAN_INFO_ONLY_OPTS: u16 = 1 << 6;
122
123bitflags! {
124 #[non_exhaustive]
125 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
126 pub struct BridgeVlanInfoFlags: u16 {
127 const Controller = BRIDGE_VLAN_INFO_CONTROLLER;
129 const Pvid = BRIDGE_VLAN_INFO_PVID;
131 const Untagged= BRIDGE_VLAN_INFO_UNTAGGED;
133 const RangeBegin = BRIDGE_VLAN_INFO_RANGE_BEGIN;
135 const RangeEnd = BRIDGE_VLAN_INFO_RANGE_END;
137 const Brentry = BRIDGE_VLAN_INFO_BRENTRY;
139 const OnlyOpts= BRIDGE_VLAN_INFO_ONLY_OPTS;
141 const _ = !0;
142 }
143}
144
145impl BridgeVlanInfoFlags {
146 pub const LENGTH: usize = 2;
147}
148
149#[derive(Debug, PartialEq, Eq, Clone, Copy)]
150pub struct BridgeVlanInfo {
151 pub flags: BridgeVlanInfoFlags,
152 pub vid: u16,
153}
154
155impl BridgeVlanInfo {
156 pub const LENGTH: usize = 4;
157}
158
159impl From<&BridgeVlanInfo> for [u8; 4] {
160 fn from(d: &BridgeVlanInfo) -> Self {
161 let mut ret = [0u8; 4];
162 emit_u16(&mut ret[0..2], d.flags.bits()).unwrap();
163 emit_u16(&mut ret[2..4], d.vid).unwrap();
164 ret
165 }
166}
167
168impl TryFrom<&[u8]> for BridgeVlanInfo {
169 type Error = DecodeError;
170 fn try_from(raw: &[u8]) -> Result<Self, DecodeError> {
171 if raw.len() == 4 {
172 Ok(Self {
173 flags: BridgeVlanInfoFlags::from_bits_retain(
174 parse_u16(&raw[0..2]).context(format!(
175 "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
176 ))?,
177 ),
178 vid: parse_u16(&raw[2..4]).context(format!(
179 "Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
180 ))?,
181 })
182 } else {
183 Err(DecodeError::from(format!(
184 "Invalid IFLA_BRIDGE_VLAN_INFO value, expecting [u8;4], but \
185 got {raw:?}"
186 )))
187 }
188 }
189}
190
191const BRIDGE_FLAGS_CONTROLLER: u16 = 1;
193const BRIDGE_FLAGS_SELF: u16 = 2;
194
195#[derive(Clone, Copy, Eq, PartialEq, Debug)]
196#[non_exhaustive]
197pub enum BridgeFlag {
198 Controller,
200 LowerDev,
202 Other(u16),
203}
204
205impl From<u16> for BridgeFlag {
206 fn from(d: u16) -> Self {
207 match d {
208 BRIDGE_FLAGS_CONTROLLER => Self::Controller,
209 BRIDGE_FLAGS_SELF => Self::LowerDev,
210 _ => Self::Other(d),
211 }
212 }
213}
214
215impl From<BridgeFlag> for u16 {
216 fn from(v: BridgeFlag) -> u16 {
217 match v {
218 BridgeFlag::Controller => BRIDGE_FLAGS_CONTROLLER,
219 BridgeFlag::LowerDev => BRIDGE_FLAGS_SELF,
220 BridgeFlag::Other(d) => d,
221 }
222 }
223}
224
225impl BridgeFlag {
226 pub const LENGTH: usize = 2;
227}
228
229const BRIDGE_MODE_VEB: u16 = 0;
230const BRIDGE_MODE_VEPA: u16 = 1;
231
232#[derive(Clone, Copy, Eq, PartialEq, Debug)]
233#[non_exhaustive]
234pub enum BridgeMode {
235 Veb,
237 Vepa,
239 Other(u16),
240}
241
242impl From<u16> for BridgeMode {
243 fn from(d: u16) -> Self {
244 match d {
245 BRIDGE_MODE_VEB => Self::Veb,
246 BRIDGE_MODE_VEPA => Self::Vepa,
247 _ => Self::Other(d),
248 }
249 }
250}
251
252impl From<BridgeMode> for u16 {
253 fn from(v: BridgeMode) -> u16 {
254 match v {
255 BridgeMode::Veb => BRIDGE_MODE_VEB,
256 BridgeMode::Vepa => BRIDGE_MODE_VEPA,
257 BridgeMode::Other(d) => d,
258 }
259 }
260}
261
262impl BridgeMode {
263 pub const LENGTH: usize = 2;
264}
265
266const IFLA_BRIDGE_VLAN_TUNNEL_ID: u16 = 1;
267const IFLA_BRIDGE_VLAN_TUNNEL_VID: u16 = 2;
268const IFLA_BRIDGE_VLAN_TUNNEL_FLAGS: u16 = 3;
269
270#[derive(Clone, Eq, PartialEq, Debug)]
271#[non_exhaustive]
272pub enum BridgeVlanTunnelInfo {
273 Id(u32),
274 Vid(u16),
275 Flags(BridgeVlanInfoFlags),
276 Other(DefaultNla),
277}
278
279impl Nla for BridgeVlanTunnelInfo {
280 fn value_len(&self) -> usize {
281 match self {
282 Self::Id(_) => 4,
283 Self::Vid(_) => 2,
284 Self::Flags(_) => BridgeVlanInfoFlags::LENGTH,
285 Self::Other(nla) => nla.value_len(),
286 }
287 }
288
289 fn emit_value(&self, buffer: &mut [u8]) {
290 match self {
291 Self::Id(v) => emit_u32(buffer, *v).unwrap(),
292 Self::Vid(v) => emit_u16(buffer, *v).unwrap(),
293 Self::Flags(value) => emit_u16(buffer, value.bits()).unwrap(),
294 Self::Other(nla) => nla.emit_value(buffer),
295 }
296 }
297
298 fn kind(&self) -> u16 {
299 match self {
300 Self::Id(_) => IFLA_BRIDGE_VLAN_TUNNEL_ID,
301 Self::Vid(_) => IFLA_BRIDGE_VLAN_TUNNEL_VID,
302 Self::Flags(_) => IFLA_BRIDGE_VLAN_TUNNEL_FLAGS,
303 Self::Other(nla) => nla.kind(),
304 }
305 }
306}
307
308impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
309 for BridgeVlanTunnelInfo
310{
311 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
312 let payload = buf.value();
313 Ok(match buf.kind() {
314 IFLA_BRIDGE_VLAN_TUNNEL_ID => {
315 Self::Id(parse_u32(payload).context(format!(
316 "Invalid IFLA_BRIDGE_VLAN_TUNNEL_ID {payload:?}"
317 ))?)
318 }
319 IFLA_BRIDGE_VLAN_TUNNEL_VID => {
320 Self::Vid(parse_u16(payload).context(format!(
321 "Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
322 ))?)
323 }
324 IFLA_BRIDGE_VLAN_TUNNEL_FLAGS => {
325 Self::Flags(BridgeVlanInfoFlags::from_bits_retain(
326 parse_u16(payload).context(format!(
327 "Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
328 ))?,
329 ))
330 }
331 _ => {
332 Self::Other(DefaultNla::parse(buf).context("Unknown NLA type")?)
333 }
334 })
335 }
336}