netlink_packet_route/link/af_spec/
unspec.rs1use anyhow::Context;
4use netlink_packet_utils::{
5 nla::{DefaultNla, Nla, NlaBuffer, NlasIterator},
6 traits::{Emitable, Parseable},
7 DecodeError,
8};
9
10use crate::link::{
11 af_spec::{VecAfSpecInet, VecAfSpecInet6},
12 AfSpecInet, AfSpecInet6,
13};
14use crate::AddressFamily;
15
16#[derive(Clone, Eq, PartialEq, Debug)]
39#[non_exhaustive]
40pub enum AfSpecUnspec {
41 Inet(Vec<AfSpecInet>),
42 Inet6(Vec<AfSpecInet6>),
43 Other(DefaultNla),
44}
45
46pub(crate) struct VecAfSpecUnspec(pub(crate) Vec<AfSpecUnspec>);
47
48impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
49 for VecAfSpecUnspec
50{
51 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
52 let mut nlas = vec![];
53 let err = "Invalid NLA for IFLA_AF_SPEC(AF_UNSPEC)";
54 for nla in NlasIterator::new(buf.into_inner()) {
55 let nla = nla.context(err)?;
56 nlas.push(match nla.kind() {
57 k if k == u8::from(AddressFamily::Inet) as u16 => {
58 AfSpecUnspec::Inet(
59 VecAfSpecInet::parse(
60 &NlaBuffer::new_checked(&nla.value())
61 .context(err)?,
62 )
63 .context(err)?
64 .0,
65 )
66 }
67 k if k == u8::from(AddressFamily::Inet6) as u16 => {
68 AfSpecUnspec::Inet6(
69 VecAfSpecInet6::parse(
70 &NlaBuffer::new_checked(&nla.value())
71 .context(err)?,
72 )
73 .context(err)?
74 .0,
75 )
76 }
77 kind => AfSpecUnspec::Other(DefaultNla::parse(&nla).context(
78 format!(
79 "Unknown AF_XXX type {kind} for IFLA_AF_SPEC(AF_UNSPEC)"
80 ),
81 )?),
82 })
83 }
84 Ok(Self(nlas))
85 }
86}
87
88impl Nla for AfSpecUnspec {
89 fn value_len(&self) -> usize {
90 match *self {
91 Self::Inet(ref nlas) => nlas.as_slice().buffer_len(),
92 Self::Inet6(ref nlas) => nlas.as_slice().buffer_len(),
93 Self::Other(ref nla) => nla.value_len(),
94 }
95 }
96
97 fn emit_value(&self, buffer: &mut [u8]) {
98 match *self {
99 Self::Inet(ref nlas) => nlas.as_slice().emit(buffer),
100 Self::Inet6(ref nlas) => nlas.as_slice().emit(buffer),
101 Self::Other(ref nla) => nla.emit_value(buffer),
102 }
103 }
104
105 fn kind(&self) -> u16 {
106 match *self {
107 Self::Inet(_) => u8::from(AddressFamily::Inet) as u16,
108 Self::Inet6(_) => u8::from(AddressFamily::Inet6) as u16,
109 Self::Other(ref nla) => nla.kind(),
110 }
111 }
112}