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