-
Notifications
You must be signed in to change notification settings - Fork 22
IPv6 Support #24
Comments
Welcome your PR. Thanks. |
Sorry for the long response, I ended up going with making a Apple TunnelProvider and using the 'createUDPSession' to connect to my rust socket, but here is what I had: Since my ipv6 implementation is pretty badly formatted, I'll let the owner make changes to it: // DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
//! Bindings to internal macOS stuff.
use libc::{c_char, c_uint, ifreq, sockaddr, sockaddr_in6, IFNAMSIZ};
use nix::{ioctl_readwrite, ioctl_write_ptr};
pub const UTUN_CONTROL_NAME: &str = "com.apple.net.utun_control";
pub const IN6_IFF_NODAD: i32 = 0x0020;
pub const IN6_IFF_SECURED: i32 = 0x0400;
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ctl_info {
pub ctl_id: c_uint,
pub ctl_name: [c_char; 96],
}
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ifaliasreq {
pub ifra_name: [c_char; IFNAMSIZ],
pub ifra_addr: sockaddr,
pub ifra_broadaddr: sockaddr,
pub ifra_mask: sockaddr,
}
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct in6_ifaliasreq {
pub ifra_name: [c_char; IFNAMSIZ],
pub ifra_addr: sockaddr_in6,
pub ifra_dstaddr: sockaddr_in6,
pub ifra_prefixmask: sockaddr_in6,
pub ifra_flags: libc::c_int,
pub in6_addrlifetime: libc::in6_addrlifetime,
}
ioctl_readwrite!(ctliocginfo, b'N', 3, ctl_info);
ioctl_write_ptr!(siocsifflags, b'i', 16, ifreq);
ioctl_readwrite!(siocgifflags, b'i', 17, ifreq);
ioctl_write_ptr!(siocsifaddr, b'i', 12, ifreq);
ioctl_readwrite!(siocgifaddr, b'i', 33, ifreq);
ioctl_write_ptr!(siocsifdstaddr, b'i', 14, ifreq);
ioctl_readwrite!(siocgifdstaddr, b'i', 34, ifreq);
ioctl_write_ptr!(siocsifbrdaddr, b'i', 19, ifreq);
ioctl_readwrite!(siocgifbrdaddr, b'i', 35, ifreq);
ioctl_write_ptr!(siocsifnetmask, b'i', 22, ifreq);
ioctl_readwrite!(siocgifnetmask, b'i', 37, ifreq);
ioctl_write_ptr!(siocsifmtu, b'i', 52, ifreq);
ioctl_readwrite!(siocgifmtu, b'i', 51, ifreq);
ioctl_write_ptr!(siocaifaddr, b'i', 26, ifaliasreq);
ioctl_write_ptr!(siocdifaddr, b'i', 25, ifreq);
// basing off: https://opensource.apple.com/source/xnu/xnu-1504.15.3/bsd/netinet6/in6_var.h
ioctl_write_ptr!(siocaifaddr_in6, b'i', 26, in6_ifaliasreq);
ioctl_write_ptr!(siocsifaddr_in6, b'i', 12, libc::in6_ifreq);
ioctl_readwrite!(siocgifaddr_in6, b'i', 33, libc::in6_ifreq); [2] let ctl = Some(posix::Fd::new(
libc::socket(
/*AF_INET*/ AF_INET6,
SOCK_DGRAM, 0,
),
true,
)?); fn set_alias(&mut self, addr: IpAddr, broadaddr: IpAddr, mask: IpAddr) -> Result<()> {
let tun_name = self.tun_name.as_ref().ok_or(Error::InvalidConfig)?;
let ctl = self.ctl.as_ref().ok_or(Error::InvalidConfig)?;
match addr {
IpAddr::V4(addr) => unsafe {
let mut req: ifaliasreq = mem::zeroed();
ptr::copy_nonoverlapping(
tun_name.as_ptr() as *const c_char,
req.ifra_name.as_mut_ptr(),
tun_name.len(),
);
req.ifra_addr = sockaddr_union::from((addr, 0)).addr;
req.ifra_broadaddr = sockaddr_union::from((broadaddr, 0)).addr;
req.ifra_mask = sockaddr_union::from((mask, 0)).addr;
if let Err(err) = siocaifaddr(ctl.as_raw_fd(), &req) {
return Err(io::Error::from(err).into());
}
let route = Route {
addr: std::net::IpAddr::V4(addr),
netmask: mask,
dest: broadaddr,
};
if let Err(e) = self.set_route(route) {
log::warn!("{e:?}");
}
Ok(())
},
IpAddr::V6(_addr) => unsafe {
let mut req: in6_ifaliasreq = mem::zeroed();
ptr::copy_nonoverlapping(
tun_name.as_ptr() as *const c_char,
req.ifra_name.as_mut_ptr(),
tun_name.len(),
);
req.ifra_addr = sockaddr_union::from((addr, 0)).addr6;
req.ifra_prefixmask = sockaddr_union::from((mask, 0)).addr6;
req.in6_addrlifetime.ia6t_vltime = 0xffffffff_u32;
req.in6_addrlifetime.ia6t_pltime = 0xffffffff_u32;
// https://opensource.apple.com/source/xnu/xnu-6153.61.1/bsd/netinet6/in6_var.h.auto.html
req.ifra_flags = IN6_IFF_NODAD;
if let Err(err) = siocaifaddr_in6(ctl.as_raw_fd(), &req) {
return Err(io::Error::from(err).into());
}
let route = Route {
addr,
netmask: mask,
dest: broadaddr,
};
if let Err(e) = self.set_route(route) {
log::warn!("{e:?}");
}
Ok(())
},
}
} |
I absolutely need IPv6 for my usecase, how close is this to being implemented for Linux and Windows? I would have the motivation to help, but I'm not very knowledgeable in low level OS subtleties and would need to do a lot of research for this one thing. |
With |
I figured out that if I commented out the |
So it is possible to use the unmodified However, I am now stuck on the problem of being able to create packets with arbitrary global unicast source addresses, and having sockets elsewhere receive them. I know that the writes are working, because I can send packets I get from the device straight back to it, and in a loop it will receive the same packet again except with a decremented hop counter. I can even modify the other fields and change the destination address as long as it is within a routing subnet for the interface. But I cannot set the destination address to something like I just figured out that copying the random link local address to the destination address and setting the port causes the packet to be received by a socket listening on |
Thoughts on what is needed to support IPv6?
It looks like rust-tun is mostly hard-wired to IPv4 (except for
PacketProtocol
) so seems non-trivial.IPv6 is supported on
tun
devices on (at least) Linux, macOS and Windows (inc.wintun.dll
and thewintun
crate) so I don't think there is any fundamental reason preventing this.This old issue (meh#4) suggests there is a key problem to solve but there are few details:
I may be able to help with this as i'm motivated to have IPv6 support in
rust-tun
.The text was updated successfully, but these errors were encountered: