Add IPv6 prefix handling to unix tun interface

This commit is contained in:
Conrad Kramer 2025-10-29 19:08:32 -07:00
parent 848efac15d
commit 3fb0269d7c
10 changed files with 229 additions and 41 deletions

View file

@ -15,6 +15,7 @@ use libc::{in6_ifreq, AF_INET6};
use socket2::{Domain, SockAddr, Socket, Type};
use tracing::{info, instrument};
use super::address::ensure_valid_ipv6_prefix;
use super::{ifname_to_string, string_to_ifname};
use crate::TunOptions;
@ -141,11 +142,36 @@ impl TunInterface {
#[throws]
#[instrument]
pub fn set_ipv6_addr(&self, addr: Ipv6Addr) {
pub fn add_ipv6_addr(&self, addr: Ipv6Addr, prefix_len: u8) {
ensure_valid_ipv6_prefix(prefix_len)?;
let mut iff = self.in6_ifreq()?;
iff.ifr6_addr.s6_addr = addr.octets();
self.perform6(|fd| unsafe { sys::if_set_addr6(fd, &iff) })?;
info!("ipv6_addr_set: {:?} (fd: {:?})", addr, self.as_raw_fd())
iff.ifr6_prefixlen = prefix_len.into();
self.perform6(|fd| unsafe { sys::if_add_addr6(fd, &iff) })?;
info!(
"ipv6_addr_added: {:?}/{} (fd: {:?})",
addr,
prefix_len,
self.as_raw_fd()
)
}
#[throws]
#[instrument]
pub fn remove_ipv6_addr(&self, addr: Ipv6Addr, prefix_len: u8) {
ensure_valid_ipv6_prefix(prefix_len)?;
let mut iff = self.in6_ifreq()?;
iff.ifr6_addr.s6_addr = addr.octets();
iff.ifr6_prefixlen = prefix_len.into();
self.perform6(|fd| unsafe { sys::if_del_addr6(fd, &iff) })?;
info!(
"ipv6_addr_removed: {:?}/{} (fd: {:?})",
addr,
prefix_len,
self.as_raw_fd()
)
}
#[throws]

View file

@ -20,7 +20,8 @@ ioctl_read_bad!(if_get_mtu, libc::SIOCGIFMTU, libc::ifreq);
ioctl_read_bad!(if_get_netmask, libc::SIOCGIFNETMASK, libc::ifreq);
ioctl_write_ptr_bad!(if_set_addr, libc::SIOCSIFADDR, libc::ifreq);
ioctl_write_ptr_bad!(if_set_addr6, libc::SIOCSIFADDR, libc::in6_ifreq);
ioctl_write_ptr_bad!(if_add_addr6, libc::SIOCSIFADDR, libc::in6_ifreq);
ioctl_write_ptr_bad!(if_del_addr6, libc::SIOCDIFADDR, 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);