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
18 changes: 9 additions & 9 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "defguard_wireguard_rs"
version = "0.7.7"
version = "0.7.8"
edition = "2024"
rust-version = "1.85"
description = "A unified multi-platform high-level API for managing WireGuard interfaces"
Expand Down
8 changes: 3 additions & 5 deletions src/bsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,7 @@ pub fn get_gateway(ip_version: IpVersion) -> Result<Option<IpAddr>, IoError> {

/// Add routing gateway.
pub fn add_gateway(dest: &IpAddrMask, gateway: IpAddr, is_blackhole: bool) -> Result<(), IoError> {
debug!(
"Adding gateway, destination: {dest}, gateway: {gateway}, is blackhole: {is_blackhole}..."
);
debug!("Adding gateway: destination {dest}, gateway {gateway}, is blackhole {is_blackhole}.");
match (dest.ip, dest.mask(), gateway) {
(IpAddr::V4(ip), IpAddr::V4(mask), IpAddr::V4(gw)) => {
let payload = DestAddrMask::<SockAddrIn>::new(ip.into(), mask.into(), gw.into());
Expand All @@ -481,7 +479,7 @@ pub fn add_gateway(dest: &IpAddrMask, gateway: IpAddr, is_blackhole: bool) -> Re

/// Remove routing gateway.
pub fn delete_gateway(dest: &IpAddrMask) -> Result<(), IoError> {
debug!("Deleting gateway with destination {dest}...");
debug!("Deleting gateway with destination {dest}.");
match (dest.ip, dest.mask()) {
(IpAddr::V4(ip), IpAddr::V4(mask)) => {
let payload =
Expand All @@ -504,7 +502,7 @@ pub fn delete_gateway(dest: &IpAddrMask) -> Result<(), IoError> {

/// Add link layer address gateway.
pub fn add_linked_route(dest: &IpAddrMask, if_name: &str) -> Result<(), IoError> {
debug!("Adding link layer gateway, destination: {dest}, interface: {if_name}");
debug!("Adding link layer gateway: destination {dest}, interface {if_name}");
let name = CString::new(if_name).unwrap();
let if_index = unsafe { libc::if_nametoindex(name.as_ptr()) as u16 };
if if_index == 0 {
Expand Down
215 changes: 104 additions & 111 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,21 +323,26 @@ pub(crate) fn add_peer_routing(

use crate::bsd::{IoError, delete_gateway};

let gateway_v4 = get_gateway(IpVersion::IPv4);
if let Ok(Some(gateway)) = gateway_v4 {
debug!("Default gateway for IPv4: {gateway}");
}
let gateway_v6 = get_gateway(IpVersion::IPv6);
if let Ok(Some(gateway)) = gateway_v6 {
debug!("Default gateway for IPv4: {gateway}");
}

debug!("Adding peer routing for interface: {ifname}");
for peer in peers {
debug!("Processing peer: {}", peer.public_key);
let mut default_route_v4 = false;
let mut default_route_v6 = false;
let mut gateway_v4 = Ok(None);
let mut gateway_v6 = Ok(None);
for addr in &peer.allowed_ips {
debug!("Processing route for allowed IP: {addr}, interface: {ifname}");
// FIXME: currently it is impossible to add another default route, so use the hack from
// wg-quick for Darwin.
if addr.ip.is_unspecified() && addr.cidr == 0 {
debug!(
"Found following default route in the allowed IPs: {addr}, interface: \
{ifname}, proceeding with default route initial setup..."
{ifname}, proceeding with default route initial setup."
);
let default1;
let default2;
Expand All @@ -346,36 +351,29 @@ pub(crate) fn add_peer_routing(
default1 = IpAddrMask::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 1);
// 128.0.0.0/1
default2 = IpAddrMask::new(IpAddr::V4(Ipv4Addr::new(128, 0, 0, 0)), 1);
gateway_v4 = get_gateway(IpVersion::IPv4);
debug!("Default gateway for IPv4 value: {gateway_v4:?}");
default_route_v4 = true;
} else {
// ::/1
default1 = IpAddrMask::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 1);
// 8000::/1
default2 =
IpAddrMask::new(IpAddr::V6(Ipv6Addr::new(0x8000, 0, 0, 0, 0, 0, 0, 0)), 1);
gateway_v6 = get_gateway(IpVersion::IPv6);
debug!("Default gateway for IPv6 value: {gateway_v6:?}");
default_route_v6 = true;
}
match add_linked_route(&default1, ifname) {
Ok(()) => debug!("Route to {default1} has been added for interface {ifname}"),
Err(err) => match err {
IoError::WriteIo(Errno::ENETUNREACH) => {
warn!(
"Failed to add default route {default1} for interface \
{ifname}: Network is unreachable. This may happen if your \
interface's IP address is not the same IP version as the \
default gateway ({default1}) that was tried to be set, in this \
case this warning can be ignored. Otherwise, there may be some \
other issues with your network configuration."
"Failed to add default route {default1} for interface {ifname}: \
Network is unreachable. This may happen if interface's IP address \
is not the same IP version as the default gateway ({default1}) \
that was tried to be set, in this case this warning can be \
ignored. Otherwise, there may be some other issues with network \
configuration."
);
}
_ => {
error!(
"Failed to add route to {default1} for interface {ifname}: \
{err}"
"Failed to add route to {default1} for interface {ifname}: {err}"
);
}
},
Expand All @@ -385,18 +383,17 @@ pub(crate) fn add_peer_routing(
Err(err) => match err {
IoError::WriteIo(Errno::ENETUNREACH) => {
warn!(
"Failed to add default route {default2} for interface \
{ifname}: Network is unreachable. This may happen if your \
interface's IP address is not the same IP version as the \
default gateway ({default2}) that was tried to be set, in this \
case this warning can be ignored. Otherwise, there may be some \
other issues with your network configuration."
"Failed to add default route {default2} for interface {ifname}: \
Network is unreachable. This may happen if interface's IP address \
is not the same IP version as the default gateway ({default2}) \
that was tried to be set, in this case this warning can be \
ignored. Otherwise, there may be some other issues with network \
configuration."
);
}
_ => {
error!(
"Failed to add route to {default2} for interface {ifname}: \
{err}"
"Failed to add route to {default2} for interface {ifname}: {err}"
);
}
},
Expand All @@ -412,107 +409,103 @@ pub(crate) fn add_peer_routing(
}
}

if default_route_v4 || default_route_v6 {
if let Some(endpoint) = peer.endpoint {
debug!("Default routes have been set, proceeding with further configuration...");
let host = IpAddrMask::host(endpoint.ip());
let localhost = if endpoint.is_ipv4() {
IpAddr::V4(Ipv4Addr::LOCALHOST)
} else {
IpAddr::V6(Ipv6Addr::LOCALHOST)
};
debug!("Cleaning up old route to {host}, if it exists...");
match delete_gateway(&host) {
Ok(()) => {
debug!(
"Previously existing route to {host} has been removed, if it existed"
);
}
Err(err) => {
debug!("Previously existing route to {host} has not been removed: {err}");
}
}
if endpoint.is_ipv6() && default_route_v6 {
// Logic below is valid only in case an endpoint has been configured for the peer.
let Some(endpoint) = peer.endpoint else {
continue;
};

let endpoint_ip = IpAddrMask::host(endpoint.ip());
let localhost = if endpoint.is_ipv4() {
IpAddr::V4(Ipv4Addr::LOCALHOST)
} else {
IpAddr::V6(Ipv6Addr::LOCALHOST)
};

match delete_gateway(&endpoint_ip) {
Ok(()) => {
debug!("Former route to {endpoint_ip} has been removed, if it existed.");
}
Err(err) => {
debug!("Former route to {endpoint_ip} has not been removed: {err}");
}
}

debug!("Default routes have been set, proceeding with further configuration.");
if endpoint.is_ipv6() {
debug!(
"Endpoint is an IPv6 address and a default IPv6 route is present in the allowed \
IPs; proceeding with further configuration."
);
match gateway_v6 {
Ok(Some(gateway)) => {
debug!(
"Endpoint is an IPv6 address and a default route (IPv6) is present in \
the alloweds IPs, proceeding with further configuration..."
"Default gateway for IPv6 has been found before: {gateway}, routing the \
traffic destined to {endpoint_ip} through it."
);
match gateway_v6 {
Ok(Some(gateway)) => {
debug!(
"Default gateway for IPv4 has been found before: {gateway}, \
routing the traffic destined to {host} through it..."
);
match add_gateway(&host, gateway, false) {
Ok(()) => {
debug!("Route to {host} has been added for gateway {gateway}");
}
Err(err) => {
error!(
"Failed to add route to {host} for gateway {gateway}: \
{err}"
);
}
}
match add_gateway(&endpoint_ip, gateway, false) {
Ok(()) => {
debug!("Route to {endpoint_ip} has been added for gateway {gateway}");
}
Ok(None) => {
debug!(
"Default gateway for IPv6 has not been found, routing the \
traffic destined to {host} through localhost as a blackhole \
route..."
Err(err) => {
error!(
"Failed to add route to {endpoint_ip} for gateway {gateway}: {err}"
);
match add_gateway(&host, localhost, true) {
Ok(()) => debug!("Blackhole route to {host} has been added"),
Err(err) => {
error!("Failed to add blackhole route to {host}: {err}");
}
}
}
}
}
Ok(None) => {
debug!(
"Default gateway for IPv6 has not been found, routing the traffic destined \
to {endpoint_ip} through localhost as a blackhole route."
);
match add_gateway(&endpoint_ip, localhost, true) {
Ok(()) => debug!("Blackhole route to {endpoint_ip} has been added"),
Err(err) => {
error!("Failed to get gateway for {host}: {err}");
error!("Failed to add blackhole route to {endpoint_ip}: {err}");
}
}
} else if default_route_v4 {
}
Err(ref err) => {
error!("Failed to get gateway for {endpoint_ip}: {err}");
}
}
} else {
debug!(
"Endpoint is an IPv4 address and a default IPv4 route is present in the allowed \
IPs; proceeding with further configuration."
);
match gateway_v4 {
Ok(Some(gateway)) => {
debug!(
"Endpoint is an IPv4 address and a default route (IPv4) is present in \
the alloweds IPs, proceeding with further configuration..."
"Default gateway for IPv4 has been found before: {gateway}, routing the \
traffic destined to {endpoint_ip} through it."
);
match gateway_v4 {
Ok(Some(gateway)) => {
debug!(
"Default gateway for IPv4 has been found before: {gateway}, \
routing the traffic destined to {host} through it..."
);
match add_gateway(&host, gateway, false) {
Ok(()) => {
debug!("Added route to {host} for gateway {gateway}");
}
Err(err) => {
error!(
"Failed to add route to {host} for gateway {gateway}: \
{err}"
);
}
}
match add_gateway(&endpoint_ip, gateway, false) {
Ok(()) => {
debug!("Added route to {endpoint_ip} for gateway {gateway}");
}
Ok(None) => {
debug!(
"Default gateway for IPv4 has not been found, routing the \
traffic destined to {host} through localhost as a blackhole \
route..."
Err(err) => {
error!(
"Failed to add route to {endpoint_ip} for gateway {gateway}: {err}"
);
match add_gateway(&host, localhost, true) {
Ok(()) => debug!("Blackhole route to {host} has been added"),
Err(err) => {
error!("Failed to add blackhole route to {host}: {err}");
}
}
}
}
}
Ok(None) => {
debug!(
"Default gateway for IPv4 has not been found, routing the traffic destined \
to {endpoint_ip} through localhost as a blackhole route."
);
match add_gateway(&endpoint_ip, localhost, true) {
Ok(()) => debug!("Blackhole route to {endpoint_ip} has been added"),
Err(err) => {
error!("Failed to get gateway for {host}: {err}");
error!("Failed to add blackhole route to {endpoint_ip}: {err}");
}
}
}
Err(ref err) => {
error!("Failed to get gateway for {endpoint_ip}: {err}");
}
}
}
}
Expand Down
Loading