Skip to content

Commit

Permalink
Multi address (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
moubctez authored Jan 6, 2025
1 parent d2ed20e commit 943f9ff
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 53 deletions.
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

0 comments on commit 943f9ff

Please sign in to comment.