GithubHelp home page GithubHelp logo

IPv6 Support about rust-tun HOT 3 OPEN

fujiapple852 avatar fujiapple852 commented on July 30, 2024
IPv6 Support

from rust-tun.

Comments (3)

DebianArch64 avatar DebianArch64 commented on July 30, 2024 2

Hey, just wanted to let you guys know that I'm currently working on PR for IPV6 support.

I got it working on Mac, need to work on the other platforms you guys support and make sure the coding style matches. Don't worry about it saying 'broadcast' in the screenshot, IPv6 doesn't support it so I just skip over it.

image

from rust-tun.

ssrlive avatar ssrlive commented on July 30, 2024

Welcome your PR. Thanks.

from rust-tun.

DebianArch64 avatar DebianArch64 commented on July 30, 2024

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:
[1] Add 'ifaddr_in6' structures mostly from libc.

//            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]
In 'set_alias' function is where we set IP address and do pretty much everything for IPV6.
'set_destination' and 'broadaddr' is useless for IPV6 and in Device::new() there needs to be a way to set family dynamically

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(())
            },
        }
    }

from rust-tun.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.