From cc30fcd34c91b572a14cce7613f399e7968b6533 Mon Sep 17 00:00:00 2001 From: Conrad Kramer Date: Sat, 20 May 2023 05:07:14 -1000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Create=20set=5Fipv6=5Faddr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a new method for setting an ipv6 address on an interface --- tun/src/unix/linux/mod.rs | 26 +++++++++++++++++++++++--- tun/src/unix/linux/sys.rs | 2 ++ tun/tests/configure.rs | 18 +++++++++++++++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tun/src/unix/linux/mod.rs b/tun/src/unix/linux/mod.rs index 4f6f882..20eabaa 100644 --- a/tun/src/unix/linux/mod.rs +++ b/tun/src/unix/linux/mod.rs @@ -4,10 +4,12 @@ use socket2::{Domain, SockAddr, Socket, Type}; use std::fs::OpenOptions; use std::io::Error; use std::mem; -use std::net::{Ipv4Addr, SocketAddrV4}; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::os::fd::RawFd; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; +use libc::in6_ifreq; + use super::{ifname_to_string, string_to_ifname}; mod sys; @@ -51,6 +53,13 @@ impl TunInterface { iff } + #[throws] + fn in6_ifreq(&self) -> in6_ifreq { + let mut iff: in6_ifreq = unsafe { mem::zeroed() }; + iff.ifr6_ifindex = self.index()?; + iff + } + #[throws] pub fn index(&self) -> i32 { let mut iff = self.ifreq()?; @@ -61,10 +70,8 @@ impl TunInterface { #[throws] pub fn set_ipv4_addr(&self, addr: Ipv4Addr) { let addr = SockAddr::from(SocketAddrV4::new(addr, 0)); - let mut iff = self.ifreq()?; iff.ifr_ifru.ifru_addr = unsafe { *addr.as_ptr() }; - self.perform(|fd| unsafe { sys::if_set_addr(fd, &iff) })?; } @@ -93,6 +100,13 @@ impl TunInterface { Ipv4Addr::from(u32::from_be(addr.sin_addr.s_addr)) } + #[throws] + pub fn set_ipv6_addr(&self, addr: Ipv6Addr) { + let mut iff = self.in6_ifreq()?; + iff.ifr6_addr.s6_addr = addr.octets(); + self.perform6(|fd| unsafe { sys::if_set_addr6(fd, &iff) })?; + } + #[throws] pub fn mtu(&self) -> i32 { let mut iff = self.ifreq()?; @@ -118,6 +132,12 @@ impl TunInterface { let socket = Socket::new(Domain::IPV4, Type::DGRAM, None)?; perform(socket.as_raw_fd())? } + + #[throws] + fn perform6(&self, perform: impl FnOnce(RawFd) -> Result) -> R { + let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?; + perform(socket.as_raw_fd())? + } } #[cfg(test)] diff --git a/tun/src/unix/linux/sys.rs b/tun/src/unix/linux/sys.rs index 8bac12d..61dd50e 100644 --- a/tun/src/unix/linux/sys.rs +++ b/tun/src/unix/linux/sys.rs @@ -4,6 +4,7 @@ use std::mem::size_of; pub use libc::ifreq; pub use libc::sockaddr; pub use libc::sockaddr_in; +pub use libc::sockaddr_in6; ioctl_write_ptr_bad!( tun_set_iff, @@ -21,5 +22,6 @@ 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_set_mtu, libc::SIOCSIFMTU, libc::ifreq); ioctl_write_ptr_bad!(if_set_netmask, libc::SIOCSIFNETMASK, libc::ifreq); diff --git a/tun/tests/configure.rs b/tun/tests/configure.rs index 29674b6..05e5ef6 100644 --- a/tun/tests/configure.rs +++ b/tun/tests/configure.rs @@ -1,7 +1,7 @@ use fehler::throws; -use tun::TunInterface; use std::io::Error; -use std::net::Ipv4Addr; +use std::net::{Ipv4Addr, Ipv6Addr}; +use tun::TunInterface; #[test] #[throws] @@ -19,4 +19,16 @@ fn test_set_get_ipv4() { let result = tun.ipv4_addr()?; assert_eq!(addr, result); -} \ No newline at end of file +} + +#[test] +#[throws] +fn test_set_get_ipv6() { + let tun = TunInterface::new()?; + + 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); +}