wireguard_uapi/linux/socket/
route_socket.rs

1use super::list_device_names_utils;
2use super::{link_message, WireGuardDeviceLinkOperation};
3use crate::err::{ConnectError, LinkDeviceError, ListDevicesError};
4use list_device_names_utils::PotentialWireGuardDeviceName;
5use neli::{
6    consts::{nl::Nlmsg, socket::NlFamily},
7    rtnl::Ifinfomsg,
8    socket::NlSocketHandle,
9};
10use std::convert::TryFrom;
11
12pub struct RouteSocket {
13    sock: NlSocketHandle,
14}
15
16impl RouteSocket {
17    pub fn connect() -> Result<Self, ConnectError> {
18        // Autoselect a PID
19        let pid = None;
20        let groups = &[];
21        let sock = NlSocketHandle::connect(NlFamily::Route, pid, groups)?;
22
23        Ok(Self { sock })
24    }
25
26    pub fn add_device(&mut self, ifname: &str) -> Result<(), LinkDeviceError> {
27        let operation = WireGuardDeviceLinkOperation::Add;
28        self.sock.send(link_message(ifname, operation)?)?;
29        self.sock.recv()?;
30
31        Ok(())
32    }
33
34    pub fn del_device(&mut self, ifname: &str) -> Result<(), LinkDeviceError> {
35        let operation = WireGuardDeviceLinkOperation::Delete;
36        self.sock.send(link_message(ifname, operation)?)?;
37        self.sock.recv()?;
38
39        Ok(())
40    }
41
42    /// Retrieves all interface names that have the string "wireguard" as an
43    /// [IFLA_INFO_KIND](libc::IFLA_INFO_KIND) value.
44    pub fn list_device_names(&mut self) -> Result<Vec<String>, ListDevicesError> {
45        self.sock
46            .send(list_device_names_utils::get_list_device_names_msg())?;
47
48        let mut iter = self.sock.iter::<Nlmsg, Ifinfomsg>(false);
49
50        let mut result_names = vec![];
51
52        while let Some(Ok(response)) = iter.next() {
53            match response.nl_type {
54                Nlmsg::Error => return Err(ListDevicesError::Unknown),
55                Nlmsg::Done => break,
56                _ => (),
57            }
58
59            let PotentialWireGuardDeviceName {
60                is_wireguard,
61                ifname,
62            } = PotentialWireGuardDeviceName::try_from(response)?;
63
64            if is_wireguard {
65                if let Some(ifname) = ifname {
66                    result_names.push(ifname);
67                }
68            }
69        }
70
71        Ok(result_names)
72    }
73}