Skip to content

Commit

Permalink
Support native IPv6 on BSD; update base64 to 0.22 (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
moubctez committed May 23, 2024
1 parent 89b80c2 commit e53e94e
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 92 deletions.
40 changes: 20 additions & 20 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
Expand Up @@ -11,7 +11,7 @@ keywords = ["wireguard", "network", "vpn"]
categories = ["network-programming"]

[dependencies]
base64 = "0.21"
base64 = "0.22"
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
Expand Down
55 changes: 36 additions & 19 deletions src/bsd/ifconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::{
os::fd::AsRawFd,
};

use libc::{c_char, kld_load, IFF_UP, IF_NAMESIZE};
#[cfg(target_os = "freebsd")]
use libc::{c_char, kld_load};
use libc::{IFF_UP, IF_NAMESIZE};
use nix::{ioctl_readwrite, ioctl_write_ptr, sys::socket::AddressFamily};

use super::{
Expand All @@ -20,11 +22,17 @@ ioctl_write_ptr!(destroy_clone_if, b'i', 121, IfReq);
// SIOCIFCREATE2
ioctl_readwrite!(create_clone_if, b'i', 124, IfReq);
// SIOCAIFADDR
#[cfg(target_os = "freebsd")]
ioctl_write_ptr!(add_addr_if, b'i', 43, InAliasReq);
#[cfg(target_os = "macos")]
ioctl_write_ptr!(add_addr_if, b'i', 26, InAliasReq);
// SIOCDIFADDR
ioctl_write_ptr!(del_addr_if, b'i', 25, IfReq);
// 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);
// SIOCDIFADDR_IN6
ioctl_write_ptr!(del_addr_if_in6, b'i', 25, IfReq6);
// SIOCSIFFLAGS
Expand All @@ -51,14 +59,17 @@ impl IfReq {

// First, try to load a kernel module for this type of network interface.
// Omit digits at the end of interface name, e.g. "wg0" -> "if_wg".
let index = if_name
.find(|c: char| c.is_ascii_digit())
.unwrap_or(if_name.len());
let mod_name = format!("if_{}", &if_name[0..index]);
unsafe {
// Ignore the return value for the time being.
// Do the cast because `c_char` differs across platforms.
kld_load(mod_name.as_ptr() as *const c_char);
#[cfg(target_os = "freebsd")]
{
let index = if_name
.find(|c: char| c.is_ascii_digit())
.unwrap_or(if_name.len());
let mod_name = format!("if_{}", &if_name[0..index]);
unsafe {
// Ignore the return value for the time being.
// Do the cast because `c_char` differs across platforms.
kld_load(mod_name.as_ptr() as *const c_char);
}
}

Self {
Expand Down Expand Up @@ -87,7 +98,7 @@ impl IfReq {
Ok(())
}

pub(super) fn delete_address(&mut self, addr: &Ipv4Addr) -> Result<(), IoError> {
pub(super) fn delete_address(&mut self, addr: Ipv4Addr) -> Result<(), IoError> {
self.ifr_ifru = addr.into();

let socket = create_socket(AddressFamily::Inet).map_err(IoError::WriteIo)?;
Expand All @@ -104,6 +115,7 @@ impl IfReq {
pub struct IfReq6 {
ifr_name: [u8; IF_NAMESIZE],
ifr_ifru: SockAddrIn6,
_padding: [u8; 244],
}

impl IfReq6 {
Expand All @@ -119,10 +131,11 @@ impl IfReq6 {
Self {
ifr_name,
ifr_ifru: SockAddrIn6::default(),
_padding: [0u8; 244],
}
}

pub(super) fn delete_address(&mut self, addr: &Ipv6Addr) -> Result<(), IoError> {
pub(super) fn delete_address(&mut self, addr: Ipv6Addr) -> Result<(), IoError> {
self.ifr_ifru = addr.into();

let socket = create_socket(AddressFamily::Inet6).map_err(IoError::WriteIo)?;
Expand All @@ -141,16 +154,17 @@ pub struct InAliasReq {
ifra_addr: SockAddrIn,
ifra_broadaddr: SockAddrIn,
ifra_mask: SockAddrIn,
#[cfg(target_os = "freebsd")]
ifra_vhid: u32,
}

impl InAliasReq {
#[must_use]
pub(super) fn new(
if_name: &str,
addr: &Ipv4Addr,
broadcast: &Ipv4Addr,
mask: &Ipv4Addr,
address: Ipv4Addr,
broadcast: Ipv4Addr,
mask: Ipv4Addr,
) -> Self {
let mut ifr_name = [0u8; IF_NAMESIZE];
if_name
Expand All @@ -161,9 +175,10 @@ impl InAliasReq {

Self {
ifr_name,
ifra_addr: addr.into(),
ifra_addr: address.into(),
ifra_broadaddr: broadcast.into(),
ifra_mask: mask.into(),
#[cfg(target_os = "freebsd")]
ifra_vhid: 0,
}
}
Expand Down Expand Up @@ -192,16 +207,17 @@ pub struct In6AliasReq {
ia6t_preferred: u64,
ia6t_vltime: u32,
ia6t_pltime: u32,
#[cfg(target_os = "freebsd")]
ifra_vhid: u32,
}

impl In6AliasReq {
#[must_use]
pub(super) fn new(
if_name: &str,
address: &Ipv6Addr,
dstaddr: &Ipv6Addr,
prefixmask: &Ipv6Addr,
address: Ipv6Addr,
// FIXME: currenlty unused: dstaddr: Ipv6Addr,
prefixmask: Ipv6Addr,
) -> Self {
let mut ifr_name = [0u8; IF_NAMESIZE];
if_name
Expand All @@ -213,13 +229,14 @@ impl In6AliasReq {
Self {
ifr_name,
ifra_addr: address.into(),
ifra_dstaddr: dstaddr.into(),
ifra_dstaddr: SockAddrIn6::zeroed(),
ifra_prefixmask: prefixmask.into(),
ifra_flags: 0,
ia6t_expire: 0,
ia6t_preferred: 0,
ia6t_vltime: ND6_INFINITE_LIFETIME,
ia6t_pltime: ND6_INFINITE_LIFETIME,
#[cfg(target_os = "freebsd")]
ifra_vhid: 0,
}
}
Expand Down
25 changes: 9 additions & 16 deletions src/bsd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#[cfg(target_os = "freebsd")]
mod ifconfig;
mod nvlist;
mod sockaddr;
mod timespec;
mod wgio;

use std::{
collections::HashMap, mem::size_of, net::IpAddr, os::fd::OwnedFd, slice::from_raw_parts,
collections::HashMap, mem::size_of, net::IpAddr, os::fd::OwnedFd, ptr::from_ref,
slice::from_raw_parts,
};

use nix::{
Expand All @@ -15,9 +15,8 @@ use nix::{
};
use thiserror::Error;

#[cfg(target_os = "freebsd")]
use self::ifconfig::{IfReq, IfReq6, IfReqFlags, In6AliasReq, InAliasReq};
use self::{
ifconfig::{IfReq, IfReq6, IfReqFlags, In6AliasReq, InAliasReq},
nvlist::NvList,
sockaddr::{pack_sockaddr, unpack_sockaddr},
timespec::{pack_timespec, unpack_timespec},
Expand Down Expand Up @@ -58,7 +57,7 @@ unsafe fn cast_ref<T>(bytes: &[u8]) -> &T {

/// Cast `T' to bytes.
unsafe fn cast_bytes<T: Sized>(p: &T) -> &[u8] {
from_raw_parts((p as *const T).cast::<u8>(), size_of::<T>())
from_raw_parts(from_ref::<T>(p).cast::<u8>(), size_of::<T>())
}

/// Create socket for ioctl communication.
Expand Down Expand Up @@ -294,7 +293,6 @@ pub fn delete_peer(if_name: &str, public_key: &Key) -> Result<(), IoError> {
wg_data.write_data()
}

#[cfg(target_os = "freebsd")]
pub fn create_interface(if_name: &str) -> Result<(), IoError> {
let mut ifreq = IfReq::new(if_name);
ifreq.create()?;
Expand All @@ -303,42 +301,37 @@ pub fn create_interface(if_name: &str) -> Result<(), IoError> {
ifreq.up()
}

#[cfg(target_os = "freebsd")]
pub fn delete_interface(if_name: &str) -> Result<(), IoError> {
let ifreq = IfReq::new(if_name);
ifreq.destroy()
}

#[cfg(target_os = "freebsd")]
pub fn assign_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError> {
let broadcast = address.broadcast();
let mask = address.mask();

match (address.ip, broadcast, mask) {
(IpAddr::V4(address), IpAddr::V4(broadcast), IpAddr::V4(mask)) => {
let inaliasreq = InAliasReq::new(if_name, &address, &broadcast, &mask);
let inaliasreq = InAliasReq::new(if_name, address, broadcast, mask);
inaliasreq.add_address()
}
// FIXME: currently doesn't work.
(IpAddr::V6(address), IpAddr::V6(broadcast), IpAddr::V6(mask)) => {
let inaliasreq = In6AliasReq::new(if_name, &address, &broadcast, &mask);
(IpAddr::V6(address), IpAddr::V6(_broadcast), IpAddr::V6(mask)) => {
let inaliasreq = In6AliasReq::new(if_name, address, mask);
inaliasreq.add_address()
}
_ => unreachable!(),
}
}

#[cfg(target_os = "freebsd")]
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)
ifreq.delete_address(address)
}
// FIXME: currently doesn't work.
IpAddr::V6(address) => {
let mut ifreq6 = IfReq6::new(if_name);
ifreq6.delete_address(&address)
ifreq6.delete_address(address)
}
}
}
Loading

0 comments on commit e53e94e

Please sign in to comment.