netlink_packet_route/link/af_spec/
unspec.rs1use netlink_packet_core::{
4 DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
5 NlasIterator, Parseable,
6};
7
8use crate::{
9 link::{
10 af_spec::{VecAfSpecInet, VecAfSpecInet6},
11 AfSpecInet, AfSpecInet6,
12 },
13 AddressFamily,
14};
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 \
80 IFLA_AF_SPEC(AF_UNSPEC)"
81 ),
82 )?),
83 })
84 }
85 Ok(Self(nlas))
86 }
87}
88
89impl Nla for AfSpecUnspec {
90 fn value_len(&self) -> usize {
91 match *self {
92 Self::Inet(ref nlas) => nlas.as_slice().buffer_len(),
93 Self::Inet6(ref nlas) => nlas.as_slice().buffer_len(),
94 Self::Other(ref nla) => nla.value_len(),
95 }
96 }
97
98 fn emit_value(&self, buffer: &mut [u8]) {
99 match *self {
100 Self::Inet(ref nlas) => nlas.as_slice().emit(buffer),
101 Self::Inet6(ref nlas) => nlas.as_slice().emit(buffer),
102 Self::Other(ref nla) => nla.emit_value(buffer),
103 }
104 }
105
106 fn kind(&self) -> u16 {
107 match *self {
108 Self::Inet(_) => u8::from(AddressFamily::Inet) as u16,
109 Self::Inet6(_) => u8::from(AddressFamily::Inet6) as u16,
110 Self::Other(ref nla) => nla.kind(),
111 }
112 }
113}