aboutsummaryrefslogtreecommitdiffstats
path: root/src/configuration/config.rs
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-10-23 10:32:18 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-10-23 10:32:18 +0200
commit3fa928b3158ce33a57e9ba2c1913485eb409ff4b (patch)
tree87562a6c84bf421a19d01ef153927f3f8315cf98 /src/configuration/config.rs
parentWork on porting timer semantics and linux platform (diff)
downloadwireguard-rs-3fa928b3158ce33a57e9ba2c1913485eb409ff4b.tar.xz
wireguard-rs-3fa928b3158ce33a57e9ba2c1913485eb409ff4b.zip
Work on platform specific code (Linux)
Diffstat (limited to 'src/configuration/config.rs')
-rw-r--r--src/configuration/config.rs260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/configuration/config.rs b/src/configuration/config.rs
new file mode 100644
index 0000000..24b1349
--- /dev/null
+++ b/src/configuration/config.rs
@@ -0,0 +1,260 @@
+use spin::Mutex;
+use std::net::{IpAddr, SocketAddr};
+use x25519_dalek::{PublicKey, StaticSecret};
+
+use super::BindOwner;
+use super::PlatformBind;
+use super::Tun;
+use super::Wireguard;
+
+/// The goal of the configuration interface is, among others,
+/// to hide the IO implementations (over which the WG device is generic),
+/// from the configuration and UAPI code.
+
+/// Describes a snapshot of the state of a peer
+pub struct PeerState {
+ rx_bytes: u64,
+ tx_bytes: u64,
+ last_handshake_time_sec: u64,
+ last_handshake_time_nsec: u64,
+ public_key: PublicKey,
+ allowed_ips: Vec<(IpAddr, u32)>,
+}
+
+struct UDPState<O: BindOwner> {
+ fwmark: Option<u32>,
+ owner: O,
+ port: u16,
+}
+
+pub struct WireguardConfig<T: Tun, B: PlatformBind> {
+ wireguard: Wireguard<T, B>,
+ network: Mutex<Option<UDPState<B::Owner>>>,
+}
+
+pub enum ConfigError {
+ NoSuchPeer,
+ NotListening,
+}
+
+impl ConfigError {
+ fn errno(&self) -> i32 {
+ // TODO: obtain the correct error values
+ match self {
+ NoSuchPeer => 1,
+ NotListening => 2,
+ }
+ }
+}
+
+/// Exposed configuration interface
+pub trait Configuration {
+ /// Updates the private key of the device
+ ///
+ /// # Arguments
+ ///
+ /// - `sk`: The new private key (or None, if the private key should be cleared)
+ fn set_private_key(&self, sk: Option<StaticSecret>);
+
+ /// Returns the private key of the device
+ ///
+ /// # Returns
+ ///
+ /// The private if set, otherwise None.
+ fn get_private_key(&self) -> Option<StaticSecret>;
+
+ /// Returns the protocol version of the device
+ ///
+ /// # Returns
+ ///
+ /// An integer indicating the protocol version
+ fn get_protocol_version(&self) -> usize;
+
+ fn set_listen_port(&self, port: u16) -> Option<ConfigError>;
+
+ /// Set the firewall mark (or similar, depending on platform)
+ ///
+ /// # Arguments
+ ///
+ /// - `mark`: The fwmark value
+ ///
+ /// # Returns
+ ///
+ /// An error if this operation is not supported by the underlying
+ /// "bind" implementation.
+ fn set_fwmark(&self, mark: Option<u32>) -> Option<ConfigError>;
+
+ /// Removes all peers from the device
+ fn replace_peers(&self);
+
+ /// Remove the peer from the
+ ///
+ /// # Arguments
+ ///
+ /// - `peer`: The public key of the peer to remove
+ ///
+ /// # Returns
+ ///
+ /// If the peer does not exists this operation is a noop
+ fn remove_peer(&self, peer: PublicKey);
+
+ /// Adds a new peer to the device
+ ///
+ /// # Arguments
+ ///
+ /// - `peer`: The public key of the peer to add
+ ///
+ /// # Returns
+ ///
+ /// A bool indicating if the peer was added.
+ ///
+ /// If the peer already exists this operation is a noop
+ fn add_peer(&self, peer: PublicKey) -> bool;
+
+ /// Update the psk of a peer
+ ///
+ /// # Arguments
+ ///
+ /// - `peer`: The public key of the peer
+ /// - `psk`: The new psk or None if the psk should be unset
+ ///
+ /// # Returns
+ ///
+ /// An error if no such peer exists
+ fn set_preshared_key(&self, peer: PublicKey, psk: Option<[u8; 32]>) -> Option<ConfigError>;
+
+ /// Update the endpoint of the
+ ///
+ /// # Arguments
+ ///
+ /// - `peer': The public key of the peer
+ /// - `psk`
+ fn set_endpoint(&self, peer: PublicKey, addr: SocketAddr) -> Option<ConfigError>;
+
+ /// Update the endpoint of the
+ ///
+ /// # Arguments
+ ///
+ /// - `peer': The public key of the peer
+ /// - `psk`
+ fn set_persistent_keepalive_interval(
+ &self,
+ peer: PublicKey,
+ interval: usize,
+ ) -> Option<ConfigError>;
+
+ /// Remove all allowed IPs from the peer
+ ///
+ /// # Arguments
+ ///
+ /// - `peer': The public key of the peer
+ ///
+ /// # Returns
+ ///
+ /// An error if no such peer exists
+ fn replace_allowed_ips(&self, peer: PublicKey) -> Option<ConfigError>;
+
+ /// Add a new allowed subnet to the peer
+ ///
+ /// # Arguments
+ ///
+ /// - `peer`: The public key of the peer
+ /// - `ip`: Subnet mask
+ /// - `masklen`:
+ ///
+ /// # Returns
+ ///
+ /// An error if the peer does not exist
+ ///
+ /// # Note:
+ ///
+ /// The API must itself sanitize the (ip, masklen) set:
+ /// The ip should be masked to remove any set bits right of the first "masklen" bits.
+ fn add_allowed_ip(&self, peer: PublicKey, ip: IpAddr, masklen: u32) -> Option<ConfigError>;
+
+ /// Returns the state of all peers
+ ///
+ /// # Returns
+ ///
+ /// A list of structures describing the state of each peer
+ fn get_peers(&self) -> Vec<PeerState>;
+}
+
+impl<T: Tun, B: PlatformBind> Configuration for WireguardConfig<T, B> {
+ fn set_private_key(&self, sk: Option<StaticSecret>) {
+ self.wireguard.set_key(sk)
+ }
+
+ fn get_private_key(&self) -> Option<StaticSecret> {
+ self.wireguard.get_sk()
+ }
+
+ fn get_protocol_version(&self) -> usize {
+ 1
+ }
+
+ fn set_listen_port(&self, port: u16) -> Option<ConfigError> {
+ let mut udp = self.network.lock();
+
+ // close the current listener
+ *udp = None;
+
+ None
+ }
+
+ fn set_fwmark(&self, mark: Option<u32>) -> Option<ConfigError> {
+ match self.network.lock().as_mut() {
+ Some(mut bind) => {
+ // there is a active bind
+ // set the fwmark (the IO operation)
+ bind.owner.set_fwmark(mark).unwrap(); // TODO: handle
+
+ // update stored value
+ bind.fwmark = mark;
+ None
+ }
+ None => Some(ConfigError::NotListening),
+ }
+ }
+
+ fn replace_peers(&self) {
+ self.wireguard.clear_peers();
+ }
+
+ fn remove_peer(&self, peer: PublicKey) {
+ self.wireguard.remove_peer(peer);
+ }
+
+ fn add_peer(&self, peer: PublicKey) -> bool {
+ self.wireguard.new_peer(peer);
+ false
+ }
+
+ fn set_preshared_key(&self, peer: PublicKey, psk: Option<[u8; 32]>) -> Option<ConfigError> {
+ None
+ }
+
+ fn set_endpoint(&self, peer: PublicKey, addr: SocketAddr) -> Option<ConfigError> {
+ None
+ }
+
+ fn set_persistent_keepalive_interval(
+ &self,
+ peer: PublicKey,
+ interval: usize,
+ ) -> Option<ConfigError> {
+ None
+ }
+
+ fn replace_allowed_ips(&self, peer: PublicKey) -> Option<ConfigError> {
+ None
+ }
+
+ fn add_allowed_ip(&self, peer: PublicKey, ip: IpAddr, masklen: u32) -> Option<ConfigError> {
+ None
+ }
+
+ fn get_peers(&self) -> Vec<PeerState> {
+ vec![]
+ }
+}