This commit is contained in:
Conrad Kramer 2025-09-23 19:56:39 -07:00
parent 85640ffce1
commit 848efac15d
10 changed files with 2625 additions and 817 deletions

View file

@ -1,4 +1,5 @@
use std::{
ffi::CStr,
io::{Error, IoSlice},
mem,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4},
@ -162,6 +163,46 @@ impl TunInterface {
tracing::warn!("Setting IPV6 address on MacOS CLI mode is not supported yet.");
}
#[throws]
#[instrument]
pub fn ipv6_addrs(&self) -> Vec<Ipv6Addr> {
struct IfAddrs(*mut libc::ifaddrs);
impl Drop for IfAddrs {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { libc::freeifaddrs(self.0) };
}
}
}
let mut ifaddrs = std::ptr::null_mut();
unsafe {
if libc::getifaddrs(&mut ifaddrs) != 0 {
Err(Error::last_os_error())?;
}
}
let guard = IfAddrs(ifaddrs);
let interface_name = self.name()?;
let mut cursor = guard.0;
let mut result = Vec::new();
while let Some(ifa) = unsafe { cursor.as_ref() } {
if !ifa.ifa_addr.is_null()
&& unsafe { (*ifa.ifa_addr).sa_family as i32 } == AF_INET6
&& unsafe { CStr::from_ptr(ifa.ifa_name) }.to_string_lossy() == interface_name
{
let sockaddr = unsafe { *(ifa.ifa_addr as *const libc::sockaddr_in6) };
result.push(Ipv6Addr::from(in6_addr_octets(sockaddr.sin6_addr)));
}
cursor = ifa.ifa_next;
}
result
}
#[throws]
fn perform<R>(&self, perform: impl FnOnce(RawFd) -> Result<R, nix::Error>) -> R {
let span = tracing::info_span!("perform", fd = self.as_raw_fd());
@ -250,3 +291,8 @@ impl TunInterface {
.map_err(|_| Error::new(ErrorKind::Other, "Conversion error"))?
}
}
#[inline]
fn in6_addr_octets(addr: libc::in6_addr) -> [u8; 16] {
unsafe { addr.__u6_addr.__u6_addr8 }
}

View file

@ -1,6 +1,7 @@
use std::{
ffi::CStr,
fs::OpenOptions,
io::{Error, Write},
io::Error,
mem,
net::{Ipv4Addr, Ipv6Addr, SocketAddrV4},
os::{
@ -10,7 +11,7 @@ use std::{
};
use fehler::throws;
use libc::in6_ifreq;
use libc::{in6_ifreq, AF_INET6};
use socket2::{Domain, SockAddr, Socket, Type};
use tracing::{info, instrument};
@ -147,6 +148,46 @@ impl TunInterface {
info!("ipv6_addr_set: {:?} (fd: {:?})", addr, self.as_raw_fd())
}
#[throws]
#[instrument]
pub fn ipv6_addrs(&self) -> Vec<Ipv6Addr> {
struct IfAddrs(*mut libc::ifaddrs);
impl Drop for IfAddrs {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { libc::freeifaddrs(self.0) };
}
}
}
let mut ifaddrs = std::ptr::null_mut();
unsafe {
if libc::getifaddrs(&mut ifaddrs) != 0 {
Err(Error::last_os_error())?;
}
}
let guard = IfAddrs(ifaddrs);
let interface_name = self.name()?;
let mut cursor = guard.0;
let mut result = Vec::new();
while let Some(ifa) = unsafe { cursor.as_ref() } {
if !ifa.ifa_addr.is_null()
&& unsafe { (*ifa.ifa_addr).sa_family as i32 } == AF_INET6
&& unsafe { CStr::from_ptr(ifa.ifa_name) }.to_string_lossy() == interface_name
{
let sockaddr = unsafe { *(ifa.ifa_addr as *const libc::sockaddr_in6) };
result.push(Ipv6Addr::from(sockaddr.sin6_addr.s6_addr));
}
cursor = ifa.ifa_next;
}
result
}
#[throws]
#[instrument]
pub fn set_mtu(&self, mtu: i32) {

View file

@ -1,6 +1,6 @@
use std::mem::size_of;
pub use libc::{ifreq, sockaddr, sockaddr_in, sockaddr_in6};
pub use libc::{ifreq, sockaddr_in};
use nix::{ioctl_read_bad, ioctl_write_ptr_bad, request_code_read, request_code_write};
ioctl_write_ptr_bad!(