Skip to content

Commit

Permalink
Add remove_endpoint_routing() (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
moubctez authored Oct 3, 2024
1 parent 713f108 commit 1bd58e2
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 32 deletions.
20 changes: 10 additions & 10 deletions Cargo.lock

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

12 changes: 4 additions & 8 deletions src/bsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,7 @@ pub fn get_gateway(ip_version: IpVersion) -> Result<Option<IpAddr>, IoError> {
}

/// Add routing gateway.
pub fn add_gateway_host(
dest: &IpAddrMask,
gateway: IpAddr,
is_blackhole: bool,
) -> Result<(), IoError> {
pub fn add_gateway(dest: &IpAddrMask, gateway: IpAddr, is_blackhole: bool) -> Result<(), IoError> {
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 @@ -386,18 +382,18 @@ pub fn add_gateway_host(
}

/// Add routing gateway.
pub fn delete_gateway_host(dest: &IpAddrMask) -> Result<(), IoError> {
pub fn delete_gateway(dest: &IpAddrMask) -> Result<(), IoError> {
match (dest.ip, dest.mask()) {
(IpAddr::V4(ip), IpAddr::V4(mask)) => {
let payload =
DestAddrMask::<SockAddrIn>::new(ip.into(), mask.into(), SockAddrIn::default());
let rtmsg = RtMessage::new_for_delete_gateway(payload);
let rtmsg = RtMessage::new_for_delete_gateway(payload, dest.is_host());
return rtmsg.execute();
}
(IpAddr::V6(ip), IpAddr::V6(mask)) => {
let payload =
DestAddrMask::<SockAddrIn6>::new(ip.into(), mask.into(), SockAddrIn6::default());
let rtmsg = RtMessage::new_for_delete_gateway(payload);
let rtmsg = RtMessage::new_for_delete_gateway(payload, dest.is_host());
return rtmsg.execute();
}
_ => error!("Unsupported address for add route"),
Expand Down
8 changes: 6 additions & 2 deletions src/bsd/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,16 @@ impl<Payload> RtMessage<Payload> {

// TODO: check if gateway field and flags are needed.
#[must_use]
pub(super) fn new_for_delete_gateway(payload: Payload) -> Self {
pub(super) fn new_for_delete_gateway(payload: Payload, is_host: bool) -> Self {
let mut flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
if is_host {
flags |= RTF_HOST;
}
let header = RtMsgHdr::new(
size_of::<Self>() as u16,
MessageType::Delete,
0,
RTF_UP | RTF_STATIC | RTF_HOST | RTF_GATEWAY,
flags,
RTA_DST | RTA_GATEWAY | RTA_NETMASK,
);

Expand Down
1 change: 1 addition & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use thiserror::Error;

#[derive(Debug, Error)]
#[non_exhaustive]
pub enum WireguardInterfaceError {
#[error("Interface setup error: {0}")]
Interface(String),
Expand Down
18 changes: 9 additions & 9 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::{
use crate::check_command_output_status;
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
use crate::{
bsd::{add_gateway_host, add_linked_route, get_gateway},
bsd::{add_gateway, add_linked_route, get_gateway},
net::IpAddrMask,
IpVersion,
};
Expand Down Expand Up @@ -238,7 +238,7 @@ pub(crate) fn add_peer_routing(
peers: &[Peer],
ifname: &str,
) -> Result<(), WireguardInterfaceError> {
use crate::bsd::delete_gateway_host;
use crate::bsd::delete_gateway;

debug!("Adding peer routing for interface: {ifname}");
for peer in peers {
Expand All @@ -253,14 +253,14 @@ 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 = get_gateway(IpVersion::IPv4).unwrap();
gateway = get_gateway(IpVersion::IPv4);
} 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 = get_gateway(IpVersion::IPv6).unwrap();
gateway = get_gateway(IpVersion::IPv6);
}
match add_linked_route(&default1, ifname) {
Ok(()) => debug!("Route to {default1} has been added for interface {ifname}"),
Expand All @@ -276,10 +276,10 @@ pub(crate) fn add_peer_routing(
}
if let Some(endpoint) = peer.endpoint {
let host = IpAddrMask::host(endpoint.ip());
if let Some(gateway) = gateway {
if let Ok(Some(gateway)) = gateway {
// Try to silently remove route to host as it may already exist.
let _ = delete_gateway_host(&host);
match add_gateway_host(&host, gateway, false) {
let _ = delete_gateway(&host);
match add_gateway(&host, gateway, false) {
Ok(()) => {
debug!("Route to {host} has been added for gateway {gateway}");
}
Expand All @@ -296,7 +296,7 @@ pub(crate) fn add_peer_routing(
} else {
IpAddr::V6(Ipv6Addr::LOCALHOST)
};
match add_gateway_host(&host, localhost, true) {
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}");
Expand Down Expand Up @@ -332,7 +332,7 @@ pub(crate) fn clean_fwmark_rules(fwmark: u32) -> Result<(), WireguardInterfaceEr
}

/// Resolves domain name to [`SocketAddr`].
pub fn resolve(addr: &str) -> Result<SocketAddr, WireguardInterfaceError> {
pub(crate) fn resolve(addr: &str) -> Result<SocketAddr, WireguardInterfaceError> {
let error = || {
WireguardInterfaceError::PeerConfigurationError(format!(
"Failed to resolve address: {addr}"
Expand Down
1 change: 0 additions & 1 deletion src/wgapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pub struct WGApi<API = Kernel> {

impl WGApi {
/// Create new instance of `WGApi`.
#[must_use]
pub fn new(ifname: String) -> Result<Self, WireguardInterfaceError> {
Ok(WGApi {
ifname,
Expand Down
16 changes: 14 additions & 2 deletions src/wgapi_userspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use std::{
time::Duration,
};

#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
use crate::bsd;
#[cfg(target_os = "linux")]
use crate::netlink;
#[cfg(any(target_os = "freebsd", target_os = "linux", target_os = "netbsd"))]
use crate::utils::clear_dns;
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
use crate::{bsd, utils::resolve};
use crate::{
check_command_output_status,
error::WireguardInterfaceError,
Expand Down Expand Up @@ -235,6 +235,18 @@ impl WireguardInterfaceApi for WGApi<Userspace> {
Ok(())
}

#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "netbsd"))]
fn remove_endpoint_routing(&self, endpoint: &str) -> Result<(), WireguardInterfaceError> {
let endpoint_addr = resolve(endpoint)?;
let host = IpAddrMask::host(endpoint_addr.ip());
match bsd::delete_gateway(&host) {
Ok(()) => debug!("Removed routing to {host}"),
Err(err) => debug!("Failed to remove routing to {host}: {err}"),
}

Ok(())
}

/// Remove WireGuard network interface.
fn remove_interface(&self) -> Result<(), WireguardInterfaceError> {
info!("Removing interface {}", self.ifname);
Expand Down
6 changes: 6 additions & 0 deletions src/wireguard_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ pub trait WireguardInterfaceApi {
/// address.
fn configure_peer_routing(&self, peers: &[Peer]) -> Result<(), WireguardInterfaceError>;

/// Remove routing to the given endpoint.
/// This is needed for proper routing table cleanup.
fn remove_endpoint_routing(&self, _endpoint: &str) -> Result<(), WireguardInterfaceError> {
Ok(())
}

/// Updates configuration of an existing WireGuard interface.
#[cfg(not(target_os = "windows"))]
fn configure_interface(
Expand Down

0 comments on commit 1bd58e2

Please sign in to comment.