Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "defguard_wireguard_rs"
version = "0.6.1"
version = "0.7.0"
edition = "2021"
rust-version = "1.80"
description = "A unified multi-platform high-level API for managing WireGuard interfaces"
Expand Down Expand Up @@ -37,7 +37,7 @@ nix = { version = "0.29", features = ["ioctl", "socket"] }
[target.'cfg(target_os = "linux")'.dependencies]
netlink-packet-core = "0.7"
netlink-packet-generic = "0.3"
netlink-packet-route = "0.20"
netlink-packet-route = "0.21"
netlink-packet-utils = "0.5"
netlink-packet-wireguard = "0.2"
netlink-sys = "0.8"
Expand Down
2 changes: 1 addition & 1 deletion examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let interface_config = InterfaceConfiguration {
name: ifname.clone(),
prvkey: "AAECAwQFBgcICQoLDA0OD/Dh0sO0pZaHeGlaSzwtHg8=".to_string(),
address: "10.6.0.30".to_string(),
addresses: vec!["10.6.0.30".parse().unwrap()],
port: 12345,
peers: vec![peer],
mtu: None,
Expand Down
2 changes: 1 addition & 1 deletion examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let interface_config = InterfaceConfiguration {
name: ifname.clone(),
prvkey: "AAECAwQFBgcICQoLDA0OD/Dh0sO0pZaHeGlaSzwtHg8=".to_string(),
address: "10.6.0.30".to_string(),
addresses: vec!["10.6.0.30".parse().unwrap()],
port: 12345,
peers: vec![peer],
mtu: None,
Expand Down
9 changes: 6 additions & 3 deletions examples/userspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn pause() {
let mut stdout = stdout();
stdout.write_all(b"Press Enter to continue...").unwrap();
stdout.flush().unwrap();
stdin().read_exact(&mut [0]).unwrap();
stdin().read(&mut [0]).unwrap();
}

#[cfg(target_os = "macos")]
Expand All @@ -22,7 +22,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let ifname: String = if cfg!(target_os = "linux") || cfg!(target_os = "freebsd") {
"wg0".into()
} else {
"utun3".into()
"utun5".into()
};
let api = WGApi::<Userspace>::new(ifname.clone())?;

Expand Down Expand Up @@ -54,7 +54,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let interface_config = InterfaceConfiguration {
name: ifname.clone(),
prvkey: "AAECAwQFBgcICQoLDA0OD/Dh0sO0pZaHeGlaSzwtHg8=".to_string(),
address: "10.6.0.30".to_string(),
addresses: vec![
"10.6.0.30".parse().unwrap(),
"fc00:def9::0a1d".parse().unwrap(),
],
port: 12345,
peers: vec![peer],
mtu: None,
Expand Down
50 changes: 44 additions & 6 deletions src/bsd/ifconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,52 @@ const ND6_INFINITE_LIFETIME: u32 = u32::MAX;

// SIOCIFDESTROY
ioctl_write_ptr!(destroy_clone_if, b'i', 121, IfReq);

// SIOCIFCREATE2
// FIXME: not on NetBSD
ioctl_readwrite!(create_clone_if, b'i', 124, IfReq);

// SIOCGIFMTU
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
ioctl_readwrite!(get_if_mtu, b'i', 51, IfMtu);
#[cfg(target_os = "netbsd")]
ioctl_readwrite!(get_if_mtu, b'i', 126, IfMtu);

// SIOCSIFMTU
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
ioctl_write_ptr!(set_if_mtu, b'i', 52, IfMtu);
#[cfg(target_os = "netbsd")]
ioctl_write_ptr!(set_if_mtu, b'i', 127, IfMtu);

// SIOCSIFADDR
ioctl_write_ptr!(set_addr_if, b'i', 12, IfReq);

// SIOCAIFADDR
#[cfg(target_os = "freebsd")]
ioctl_write_ptr!(add_addr_if, b'i', 43, InAliasReq);
#[cfg(any(target_os = "macos", target_os = "netbsd"))]
ioctl_write_ptr!(add_addr_if, b'i', 26, InAliasReq);

// SIOCDIFADDR
ioctl_write_ptr!(del_addr_if, b'i', 25, IfReq);

// SIOCSIFADDR_IN6
ioctl_write_ptr!(set_addr_if_in6, b'i', 12, IfReq6);

// SIOCAIFADDR_IN6
#[cfg(target_os = "freebsd")]
ioctl_write_ptr!(add_addr_if_in6, b'i', 27, In6AliasReq);
#[cfg(target_os = "macos")]
ioctl_write_ptr!(add_addr_if_in6, b'i', 26, In6AliasReq);
#[cfg(target_os = "netbsd")]
ioctl_write_ptr!(add_addr_if_in6, b'i', 107, In6AliasReq);

// SIOCDIFADDR_IN6
ioctl_write_ptr!(del_addr_if_in6, b'i', 25, IfReq6);

// SIOCSIFFLAGS
ioctl_write_ptr!(set_if_flags, b'i', 16, IfReqFlags);

// SIOCGIFFLAGS
ioctl_readwrite!(get_if_flags, b'i', 17, IfReqFlags);

Expand All @@ -71,6 +86,14 @@ pub struct IfReq {
}

impl IfReq {
#[must_use]
pub(super) fn new_with_address(if_name: &str, address: Ipv4Addr) -> Self {
Self {
ifr_name: make_ifr_name(if_name),
ifr_ifru: address.into(),
}
}

#[must_use]
pub(super) fn new(if_name: &str) -> Self {
Self {
Expand Down Expand Up @@ -99,9 +122,16 @@ impl IfReq {
Ok(())
}

pub(super) fn delete_address(&mut self, addr: Ipv4Addr) -> Result<(), IoError> {
self.ifr_ifru = addr.into();
pub(super) fn set_address(&self) -> Result<(), IoError> {
let socket = create_socket(AddressFamily::Inet).map_err(IoError::WriteIo)?;
unsafe {
set_addr_if(socket.as_raw_fd(), self).map_err(IoError::WriteIo)?;
}

Ok(())
}

pub(super) fn delete_address(&self) -> Result<(), IoError> {
let socket = create_socket(AddressFamily::Inet).map_err(IoError::WriteIo)?;
unsafe {
del_addr_if(socket.as_raw_fd(), self).map_err(IoError::WriteIo)?;
Expand Down Expand Up @@ -161,17 +191,25 @@ pub struct IfReq6 {

impl IfReq6 {
#[must_use]
pub(super) fn new(if_name: &str) -> Self {
pub(super) fn new_with_address(if_name: &str, address: Ipv6Addr) -> Self {
Self {
ifr_name: make_ifr_name(if_name),
ifr_ifru: SockAddrIn6::default(),
ifr_ifru: address.into(),
_padding: [0u8; 244],
}
}

pub(super) fn delete_address(&mut self, addr: Ipv6Addr) -> Result<(), IoError> {
self.ifr_ifru = addr.into();
pub(super) fn set_address(&self) -> Result<(), IoError> {
let socket = create_socket(AddressFamily::Inet6).map_err(IoError::WriteIo)?;

unsafe {
set_addr_if_in6(socket.as_raw_fd(), self).map_err(IoError::WriteIo)?;
}

Ok(())
}

pub(super) fn delete_address(&self) -> Result<(), IoError> {
let socket = create_socket(AddressFamily::Inet6).map_err(IoError::WriteIo)?;
unsafe {
del_addr_if_in6(socket.as_raw_fd(), self).map_err(IoError::WriteIo)?;
Expand Down
21 changes: 17 additions & 4 deletions src/bsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,19 @@ pub fn delete_interface(if_name: &str) -> Result<(), IoError> {
ifreq.destroy()
}

pub fn set_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError> {
match address.ip {
IpAddr::V4(address) => {
let ifreq = IfReq::new_with_address(if_name, address);
ifreq.set_address()
}
IpAddr::V6(address) => {
let ifreq6 = IfReq6::new_with_address(if_name, address);
ifreq6.set_address()
}
}
}

pub fn assign_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError> {
let broadcast = address.broadcast();
let mask = address.mask();
Expand All @@ -347,12 +360,12 @@ pub fn assign_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError
pub fn remove_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError> {
match address.ip {
IpAddr::V4(address) => {
let mut ifreq = IfReq::new(if_name);
ifreq.delete_address(address)
let ifreq = IfReq::new_with_address(if_name, address);
ifreq.delete_address()
}
IpAddr::V6(address) => {
let mut ifreq6 = IfReq6::new(if_name);
ifreq6.delete_address(address)
let ifreq6 = IfReq6::new_with_address(if_name, address);
ifreq6.delete_address()
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
//! let interface_config = InterfaceConfiguration {
//! name: ifname.clone(),
//! prvkey: "AAECAwQFBgcICQoLDA0OD/Dh0sO0pZaHeGlaSzwtHg8=".to_string(),
//! address: "10.6.0.30".to_string(),
//! addresses: vec!["10.6.0.30".parse().unwrap()],
//! port: 12345,
//! peers: vec![],
//! mtu: None,
Expand Down Expand Up @@ -98,13 +98,13 @@ pub enum IpVersion {
IPv6,
}

/// Host WireGuard interface configuration
/// Host WireGuard interface configuration.
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct InterfaceConfiguration {
pub name: String,
pub prvkey: String,
pub address: String,
pub addresses: Vec<IpAddrMask>,
pub port: u32,
pub peers: Vec<Peer>,
/// Maximum transfer unit. `None` means do not set MTU, but keep the system default.
Expand All @@ -116,7 +116,7 @@ impl fmt::Debug for InterfaceConfiguration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InterfaceConfiguration")
.field("name", &self.name)
.field("address", &self.address)
.field("addresses", &self.addresses)
.field("port", &self.port)
.field("peers", &self.peers)
.field("mtu", &self.mtu)
Expand Down
27 changes: 13 additions & 14 deletions src/wgapi_linux.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{net::IpAddr, str::FromStr};
use std::net::IpAddr;

use crate::{
netlink,
Expand Down Expand Up @@ -50,17 +50,15 @@ impl WireguardInterfaceApi for WGApi<Kernel> {
self.ifname
);

// assign IP address to interface
debug!(
"Assigning address {} to interface {}",
config.address, self.ifname
);
let address = IpAddrMask::from_str(&config.address)?;
self.assign_address(&address)?;
debug!(
"Address {} assigned to interface {} successfully",
config.address, self.ifname
);
// Assign IP addresses to the interface.
for address in &config.addresses {
debug!("Assigning address {address} to interface {}", self.ifname);
self.assign_address(&address)?;
debug!(
"Address {address} assigned to interface {} successfully",
self.ifname
);
}

// configure interface
debug!(
Expand Down Expand Up @@ -88,8 +86,9 @@ impl WireguardInterfaceApi for WGApi<Kernel> {
}

info!(
"Interface {} has been successfully configured. It has been assigned the following address: {}",
self.ifname, address
"Interface {} has been successfully configured. \
It has been assigned the following addresses: {:?}",
self.ifname, config.addresses
);
debug!(
"Interface {} configured with config: {config:?}",
Expand Down
Loading