Skip to content
Open
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
12 changes: 5 additions & 7 deletions tun/src/unix/apple/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::{
io::{Error, IoSlice},
mem,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4},
os::fd::{AsRawFd, FromRawFd, RawFd},
};
use std::{io::{Error, IoSlice}, mem, net::{Ipv4Addr, SocketAddrV4}, os::fd::{AsRawFd, FromRawFd, RawFd}, ptr};
use std::net::{IpAddr, Ipv6Addr, SocketAddrV6};
use std::ptr::addr_of;

use byteorder::{ByteOrder, NetworkEndian};
use fehler::throws;
use libc::{c_char, iovec, writev, AF_INET, AF_INET6};
use libc::{c_char, iovec, sockaddr_in6, writev, AF_INET, AF_INET6};
use nix::sys::socket::SockaddrIn6;
use socket2::{Domain, SockAddr, Socket, Type};
use tracing::{self, instrument};

Expand Down
23 changes: 21 additions & 2 deletions tun/src/unix/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{
fs::OpenOptions,
io::{Error, Write},
mem,
net::{Ipv4Addr, Ipv6Addr, SocketAddrV4},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4},
os::{
fd::RawFd,
unix::io::{AsRawFd, FromRawFd, IntoRawFd},
Expand All @@ -15,7 +15,7 @@ use socket2::{Domain, SockAddr, Socket, Type};
use tracing::{info, instrument};

use super::{ifname_to_string, string_to_ifname};
use crate::TunOptions;
use crate::{syscall, TunOptions};

mod sys;

Expand Down Expand Up @@ -114,6 +114,25 @@ impl TunInterface {
Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr))
}

#[throws]
#[instrument]
pub fn ipv6_addrs(&self) -> Vec<Ipv6Addr> {
let ip_addrs = self.ip_addrs()?;
let mut ipv6_addrs: Vec<Ipv6Addr> = vec![];

for ip_addr in ip_addrs.iter() {
if ip_addr.is_ipv6() {
match ip_addr {
IpAddr::V6(addr) => {
ipv6_addrs.push(*addr);
}
_ => {}
}
}
}
ipv6_addrs
}

#[throws]
#[instrument]
pub fn set_broadcast_addr(&self, addr: Ipv4Addr) {
Expand Down
10 changes: 10 additions & 0 deletions tun/src/unix/linux/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,13 @@ ioctl_write_ptr_bad!(if_set_addr6, libc::SIOCSIFADDR, libc::in6_ifreq);
ioctl_write_ptr_bad!(if_set_brdaddr, libc::SIOCSIFBRDADDR, libc::ifreq);
ioctl_write_ptr_bad!(if_set_mtu, libc::SIOCSIFMTU, libc::ifreq);
ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq);

#[macro_export]
macro_rules! syscall {
($call: ident ( $($arg: expr),* $(,)* ) ) => {{
match unsafe { ::libc::$call($($arg, )*) } {
-1 => Err(::std::io::Error::last_os_error()),
res => Ok(res),
}
}};
}
46 changes: 46 additions & 0 deletions tun/src/unix/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
use std::{
ffi::CStr,
io::Error,
mem,
mem::MaybeUninit,
net::{IpAddr, SocketAddr},
os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
};

use tracing::instrument;

use crate::syscall;

mod queue;

#[cfg(target_vendor = "apple")]
Expand Down Expand Up @@ -60,6 +65,47 @@ impl TunInterface {
pub fn set_nonblocking(&mut self, nb: bool) {
self.socket.set_nonblocking(nb)?;
}

#[throws]
#[instrument]
pub fn ip_addrs(&self) -> Vec<IpAddr> {
let mut result: Vec<IpAddr> = vec![];
let mut addrs: *mut libc::ifaddrs = std::ptr::null_mut();
let if_name = self.name()?;
syscall!(getifaddrs(&mut addrs as *mut _))?;
unsafe {
while !addrs.is_null() {
let addr = &*addrs;
addrs = addr.ifa_next;

let name = CStr::from_ptr(addr.ifa_name).to_str().unwrap();
if if_name != name {
continue;
}
let family = (*addr.ifa_addr).sa_family;
let addr_len = match family as i32 {
libc::AF_INET => mem::size_of::<libc::sockaddr_in>(),
libc::AF_INET6 => mem::size_of::<libc::sockaddr_in6>(),
_ => continue,
};

let (_, sock_addr) = socket2::SockAddr::try_init(|addr_storage, len| {
*len = addr_len as u32;
std::ptr::copy_nonoverlapping(
addr.ifa_addr as *const libc::c_void,
addr_storage as *mut _,
addr_len,
);
Ok(())
})?;

if let Some(socket_addr) = sock_addr.as_socket() {
result.push(socket_addr.ip());
}
}
}
result
}
}

#[instrument]
Expand Down
5 changes: 2 additions & 3 deletions tun/tests/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ fn test_set_get_ipv6() {

let addr = Ipv6Addr::new(1, 1, 1, 1, 1, 1, 1, 1);
tun.set_ipv6_addr(addr)?;

// let result = tun.ipv6_addr()?;
// assert_eq!(addr, result);
let result = tun.ipv6_addrs()?[0];
assert_eq!(addr, result);
}

#[test]
Expand Down