1use netlink_packet_core::{
4 parse_u8, DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer,
5 NlasIterator, Parseable,
6};
7
8const ETH_ALEN: usize = 6;
9const NL80211_ATTR_MAC: u16 = 6;
10const NL80211_ATTR_MLO_LINK_ID: u16 = 313;
11
12#[derive(Debug, PartialEq, Eq, Clone)]
13enum Nl80211MloLinkNla {
14 Id(u8),
15 Mac([u8; ETH_ALEN]),
16 Other(DefaultNla),
17}
18
19impl Nla for Nl80211MloLinkNla {
20 fn value_len(&self) -> usize {
21 match self {
22 Self::Id(_) => 1,
23 Self::Mac(_) => ETH_ALEN,
24 Self::Other(attr) => attr.value_len(),
25 }
26 }
27
28 fn kind(&self) -> u16 {
29 match self {
30 Self::Id(_) => NL80211_ATTR_MLO_LINK_ID,
31 Self::Mac(_) => NL80211_ATTR_MAC,
32 Self::Other(attr) => attr.kind(),
33 }
34 }
35
36 fn emit_value(&self, buffer: &mut [u8]) {
37 match self {
38 Self::Id(d) => buffer[0] = *d,
39 Self::Mac(s) => buffer.copy_from_slice(s),
40 Self::Other(attr) => attr.emit(buffer),
41 }
42 }
43}
44
45impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
46 for Nl80211MloLinkNla
47{
48 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
49 let payload = buf.value();
50 Ok(match buf.kind() {
51 NL80211_ATTR_MLO_LINK_ID => {
52 let err_msg = format!(
53 "Invalid NL80211_ATTR_MLO_LINK_ID value {payload:?}"
54 );
55 Self::Id(parse_u8(payload).context(err_msg)?)
56 }
57 NL80211_ATTR_MAC => Self::Mac(if payload.len() == ETH_ALEN {
58 let mut ret = [0u8; ETH_ALEN];
59 ret.copy_from_slice(&payload[..ETH_ALEN]);
60 ret
61 } else {
62 return Err(format!(
63 "Invalid length of NL80211_ATTR_MAC, expected length {ETH_ALEN} got {payload:?}"
64 )
65 .into());
66 }),
67 _ => Self::Other(
68 DefaultNla::parse(buf).context("invalid NLA (unknown kind)")?,
69 ),
70 })
71 }
72}
73
74#[derive(Debug, PartialEq, Eq, Clone, Default)]
76#[non_exhaustive]
77pub struct Nl80211MloLink {
78 pub id: u8,
79 pub mac: [u8; ETH_ALEN],
80}
81
82impl Nla for Nl80211MloLink {
83 fn value_len(&self) -> usize {
84 Vec::<Nl80211MloLinkNla>::from(self).as_slice().buffer_len()
85 }
86
87 fn kind(&self) -> u16 {
88 self.id as u16 + 1
89 }
90
91 fn emit_value(&self, buffer: &mut [u8]) {
92 Vec::<Nl80211MloLinkNla>::from(self).as_slice().emit(buffer)
93 }
94}
95
96impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
97 for Nl80211MloLink
98{
99 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
100 let mut ret = Self::default();
101 let payload = buf.value();
102 let err_msg =
103 format!("Invalid NL80211_ATTR_MLO_LINKS value {payload:?}");
104 for nla in NlasIterator::new(payload) {
105 let nla = &nla.context(err_msg.clone())?;
106 match Nl80211MloLinkNla::parse(nla).context(err_msg.clone())? {
107 Nl80211MloLinkNla::Id(d) => ret.id = d,
108 Nl80211MloLinkNla::Mac(s) => ret.mac = s,
109 Nl80211MloLinkNla::Other(attr) => {
110 log::warn!(
111 "Got unsupported NL80211_ATTR_MLO_LINKS value {attr:?}"
112 )
113 }
114 }
115 }
116 Ok(ret)
117 }
118}
119
120impl From<&Nl80211MloLink> for Vec<Nl80211MloLinkNla> {
121 fn from(link: &Nl80211MloLink) -> Self {
122 vec![
123 Nl80211MloLinkNla::Id(link.id),
124 Nl80211MloLinkNla::Mac(link.mac),
125 ]
126 }
127}