neli_wifi/
interface.rs

1use crate::attr::{Attrs, Nl80211Attr};
2
3use neli::attr::Attribute;
4use neli::err::DeError;
5
6/// A struct representing a wifi interface
7#[non_exhaustive]
8#[derive(Debug, Default, Clone, PartialEq, Eq)]
9pub struct Interface {
10    /// A netlink interface index. This index is used to fetch extra information with nl80211
11    pub index: Option<i32>,
12    /// Interface essid
13    pub ssid: Option<Vec<u8>>,
14    /// Interface MAC address
15    pub mac: Option<Vec<u8>>,
16    /// Interface name (u8, String)
17    pub name: Option<Vec<u8>>,
18    /// Interface frequency of the selected channel (MHz)
19    pub frequency: Option<u32>,
20    /// Interface chanel
21    pub channel: Option<u32>,
22    /// Interface transmit power level in signed mBm units.
23    pub power: Option<u32>,
24    /// index of wiphy to operate on, cf. /sys/class/ieee80211/<phyname>/index
25    pub phy: Option<u32>,
26    /// Wireless device identifier, used for pseudo-devices that don't have a netdev
27    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}