1use crate::attr::{Attrs, Nl80211Attr};
2
3use neli::attr::Attribute;
4use neli::err::DeError;
5
6#[non_exhaustive]
8#[derive(Debug, Default, Clone, PartialEq, Eq)]
9pub struct Interface {
10 pub index: Option<i32>,
12 pub ssid: Option<Vec<u8>>,
14 pub mac: Option<Vec<u8>>,
16 pub name: Option<Vec<u8>>,
18 pub frequency: Option<u32>,
20 pub channel: Option<u32>,
22 pub power: Option<u32>,
24 pub phy: Option<u32>,
26 pub device: Option<u64>,
28}
29
30impl TryFrom<Attrs<'_, Nl80211Attr>> for Interface {
31 type Error = DeError;
32
33 fn try_from(attrs: Attrs<'_, Nl80211Attr>) -> Result<Self, Self::Error> {
34 let mut res = Self::default();
35 for attr in attrs.iter() {
36 match attr.nla_type.nla_type {
37 Nl80211Attr::AttrIfindex => {
38 res.index = Some(attr.get_payload_as()?);
39 }
40 Nl80211Attr::AttrSsid => {
41 res.ssid = Some(attr.get_payload_as_with_len()?);
42 }
43 Nl80211Attr::AttrMac => {
44 res.mac = Some(attr.get_payload_as_with_len()?);
45 }
46 Nl80211Attr::AttrIfname => {
47 res.name = Some(attr.get_payload_as_with_len()?);
48 }
49 Nl80211Attr::AttrWiphyFreq => {
50 res.frequency = Some(attr.get_payload_as()?);
51 }
52 Nl80211Attr::AttrChannelWidth => {
53 res.channel = Some(attr.get_payload_as()?);
54 }
55 Nl80211Attr::AttrWiphyTxPowerLevel => {
56 res.power = Some(attr.get_payload_as()?);
57 }
58 Nl80211Attr::AttrWiphy => res.phy = Some(attr.get_payload_as()?),
59 Nl80211Attr::AttrWdev => res.device = Some(attr.get_payload_as()?),
60 _ => (),
61 }
62 }
63 Ok(res)
64 }
65}
66
67#[cfg(test)]
68mod test_interface {
69 use super::*;
70 use crate::attr::Nl80211Attr::*;
71 use neli::attr::AttrHandle;
72 use neli::genl::{AttrType, Nlattr};
73 use neli::types::Buffer;
74
75 fn new_attr(t: Nl80211Attr, d: Vec<u8>) -> Nlattr<Nl80211Attr, Buffer> {
76 Nlattr {
77 nla_len: (4 + d.len()) as _,
78 nla_type: AttrType {
79 nla_nested: false,
80 nla_network_order: true,
81 nla_type: t,
82 },
83 nla_payload: d.into(),
84 }
85 }
86
87 #[test]
88 fn test_parser() {
89 let handler = vec![
90 new_attr(AttrIfindex, vec![3, 0, 0, 0]),
91 new_attr(AttrIfname, vec![119, 108, 112, 53, 115, 48]),
92 new_attr(AttrWiphy, vec![0, 0, 0, 0]),
93 new_attr(AttrIftype, vec![2, 0, 0, 0]),
94 new_attr(AttrWdev, vec![1, 0, 0, 0, 0, 0, 0, 0]),
95 new_attr(AttrMac, vec![255, 255, 255, 255, 255, 255]),
96 new_attr(AttrWiphyFreq, vec![108, 9, 0, 0]),
97 new_attr(AttrChannelWidth, vec![1, 0, 0, 0]),
98 new_attr(AttrWiphyTxPowerLevel, vec![164, 6, 0, 0]),
99 new_attr(AttrSsid, vec![101, 100, 117, 114, 111, 97, 109]),
100 ];
101
102 let interface: Interface = AttrHandle::new(handler.into_iter().collect())
103 .try_into()
104 .unwrap();
105 let expected_interface = Interface {
106 index: Some(3),
107 ssid: Some(vec![101, 100, 117, 114, 111, 97, 109]),
108 mac: Some(vec![255, 255, 255, 255, 255, 255]),
109 name: Some(vec![119, 108, 112, 53, 115, 48]),
110 frequency: Some(u32::from_le_bytes([108, 9, 0, 0])),
111 channel: Some(u32::from_le_bytes([1, 0, 0, 0])),
112 power: Some(u32::from_le_bytes([164, 6, 0, 0])),
113 phy: Some(u32::from_le_bytes([0, 0, 0, 0])),
114 device: Some(u64::from_le_bytes([1, 0, 0, 0, 0, 0, 0, 0])),
115 };
116
117 assert_eq!(interface, expected_interface)
118 }
119}