Skip to content

Commit e53e94e

Browse files
authored
Support native IPv6 on BSD; update base64 to 0.22 (#57)
1 parent 89b80c2 commit e53e94e

9 files changed

+142
-92
lines changed

Cargo.lock

+20-20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ keywords = ["wireguard", "network", "vpn"]
1111
categories = ["network-programming"]
1212

1313
[dependencies]
14-
base64 = "0.21"
14+
base64 = "0.22"
1515
log = "0.4"
1616
serde = { version = "1.0", features = ["derive"] }
1717
thiserror = "1.0"

src/bsd/ifconfig.rs

+36-19
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use std::{
33
os::fd::AsRawFd,
44
};
55

6-
use libc::{c_char, kld_load, IFF_UP, IF_NAMESIZE};
6+
#[cfg(target_os = "freebsd")]
7+
use libc::{c_char, kld_load};
8+
use libc::{IFF_UP, IF_NAMESIZE};
79
use nix::{ioctl_readwrite, ioctl_write_ptr, sys::socket::AddressFamily};
810

911
use super::{
@@ -20,11 +22,17 @@ ioctl_write_ptr!(destroy_clone_if, b'i', 121, IfReq);
2022
// SIOCIFCREATE2
2123
ioctl_readwrite!(create_clone_if, b'i', 124, IfReq);
2224
// SIOCAIFADDR
25+
#[cfg(target_os = "freebsd")]
2326
ioctl_write_ptr!(add_addr_if, b'i', 43, InAliasReq);
27+
#[cfg(target_os = "macos")]
28+
ioctl_write_ptr!(add_addr_if, b'i', 26, InAliasReq);
2429
// SIOCDIFADDR
2530
ioctl_write_ptr!(del_addr_if, b'i', 25, IfReq);
2631
// SIOCAIFADDR_IN6
32+
#[cfg(target_os = "freebsd")]
2733
ioctl_write_ptr!(add_addr_if_in6, b'i', 27, In6AliasReq);
34+
#[cfg(target_os = "macos")]
35+
ioctl_write_ptr!(add_addr_if_in6, b'i', 26, In6AliasReq);
2836
// SIOCDIFADDR_IN6
2937
ioctl_write_ptr!(del_addr_if_in6, b'i', 25, IfReq6);
3038
// SIOCSIFFLAGS
@@ -51,14 +59,17 @@ impl IfReq {
5159

5260
// First, try to load a kernel module for this type of network interface.
5361
// Omit digits at the end of interface name, e.g. "wg0" -> "if_wg".
54-
let index = if_name
55-
.find(|c: char| c.is_ascii_digit())
56-
.unwrap_or(if_name.len());
57-
let mod_name = format!("if_{}", &if_name[0..index]);
58-
unsafe {
59-
// Ignore the return value for the time being.
60-
// Do the cast because `c_char` differs across platforms.
61-
kld_load(mod_name.as_ptr() as *const c_char);
62+
#[cfg(target_os = "freebsd")]
63+
{
64+
let index = if_name
65+
.find(|c: char| c.is_ascii_digit())
66+
.unwrap_or(if_name.len());
67+
let mod_name = format!("if_{}", &if_name[0..index]);
68+
unsafe {
69+
// Ignore the return value for the time being.
70+
// Do the cast because `c_char` differs across platforms.
71+
kld_load(mod_name.as_ptr() as *const c_char);
72+
}
6273
}
6374

6475
Self {
@@ -87,7 +98,7 @@ impl IfReq {
8798
Ok(())
8899
}
89100

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

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

109121
impl IfReq6 {
@@ -119,10 +131,11 @@ impl IfReq6 {
119131
Self {
120132
ifr_name,
121133
ifr_ifru: SockAddrIn6::default(),
134+
_padding: [0u8; 244],
122135
}
123136
}
124137

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

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

147161
impl InAliasReq {
148162
#[must_use]
149163
pub(super) fn new(
150164
if_name: &str,
151-
addr: &Ipv4Addr,
152-
broadcast: &Ipv4Addr,
153-
mask: &Ipv4Addr,
165+
address: Ipv4Addr,
166+
broadcast: Ipv4Addr,
167+
mask: Ipv4Addr,
154168
) -> Self {
155169
let mut ifr_name = [0u8; IF_NAMESIZE];
156170
if_name
@@ -161,9 +175,10 @@ impl InAliasReq {
161175

162176
Self {
163177
ifr_name,
164-
ifra_addr: addr.into(),
178+
ifra_addr: address.into(),
165179
ifra_broadaddr: broadcast.into(),
166180
ifra_mask: mask.into(),
181+
#[cfg(target_os = "freebsd")]
167182
ifra_vhid: 0,
168183
}
169184
}
@@ -192,16 +207,17 @@ pub struct In6AliasReq {
192207
ia6t_preferred: u64,
193208
ia6t_vltime: u32,
194209
ia6t_pltime: u32,
210+
#[cfg(target_os = "freebsd")]
195211
ifra_vhid: u32,
196212
}
197213

198214
impl In6AliasReq {
199215
#[must_use]
200216
pub(super) fn new(
201217
if_name: &str,
202-
address: &Ipv6Addr,
203-
dstaddr: &Ipv6Addr,
204-
prefixmask: &Ipv6Addr,
218+
address: Ipv6Addr,
219+
// FIXME: currenlty unused: dstaddr: Ipv6Addr,
220+
prefixmask: Ipv6Addr,
205221
) -> Self {
206222
let mut ifr_name = [0u8; IF_NAMESIZE];
207223
if_name
@@ -213,13 +229,14 @@ impl In6AliasReq {
213229
Self {
214230
ifr_name,
215231
ifra_addr: address.into(),
216-
ifra_dstaddr: dstaddr.into(),
232+
ifra_dstaddr: SockAddrIn6::zeroed(),
217233
ifra_prefixmask: prefixmask.into(),
218234
ifra_flags: 0,
219235
ia6t_expire: 0,
220236
ia6t_preferred: 0,
221237
ia6t_vltime: ND6_INFINITE_LIFETIME,
222238
ia6t_pltime: ND6_INFINITE_LIFETIME,
239+
#[cfg(target_os = "freebsd")]
223240
ifra_vhid: 0,
224241
}
225242
}

src/bsd/mod.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
#[cfg(target_os = "freebsd")]
21
mod ifconfig;
32
mod nvlist;
43
mod sockaddr;
54
mod timespec;
65
mod wgio;
76

87
use std::{
9-
collections::HashMap, mem::size_of, net::IpAddr, os::fd::OwnedFd, slice::from_raw_parts,
8+
collections::HashMap, mem::size_of, net::IpAddr, os::fd::OwnedFd, ptr::from_ref,
9+
slice::from_raw_parts,
1010
};
1111

1212
use nix::{
@@ -15,9 +15,8 @@ use nix::{
1515
};
1616
use thiserror::Error;
1717

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

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

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

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

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

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

317313
match (address.ip, broadcast, mask) {
318314
(IpAddr::V4(address), IpAddr::V4(broadcast), IpAddr::V4(mask)) => {
319-
let inaliasreq = InAliasReq::new(if_name, &address, &broadcast, &mask);
315+
let inaliasreq = InAliasReq::new(if_name, address, broadcast, mask);
320316
inaliasreq.add_address()
321317
}
322-
// FIXME: currently doesn't work.
323-
(IpAddr::V6(address), IpAddr::V6(broadcast), IpAddr::V6(mask)) => {
324-
let inaliasreq = In6AliasReq::new(if_name, &address, &broadcast, &mask);
318+
(IpAddr::V6(address), IpAddr::V6(_broadcast), IpAddr::V6(mask)) => {
319+
let inaliasreq = In6AliasReq::new(if_name, address, mask);
325320
inaliasreq.add_address()
326321
}
327322
_ => unreachable!(),
328323
}
329324
}
330325

331-
#[cfg(target_os = "freebsd")]
332326
pub fn remove_address(if_name: &str, address: &IpAddrMask) -> Result<(), IoError> {
333327
match address.ip {
334328
IpAddr::V4(address) => {
335329
let mut ifreq = IfReq::new(if_name);
336-
ifreq.delete_address(&address)
330+
ifreq.delete_address(address)
337331
}
338-
// FIXME: currently doesn't work.
339332
IpAddr::V6(address) => {
340333
let mut ifreq6 = IfReq6::new(if_name);
341-
ifreq6.delete_address(&address)
334+
ifreq6.delete_address(address)
342335
}
343336
}
344337
}

0 commit comments

Comments
 (0)