diff --git a/src/lib.rs b/src/lib.rs index 94c1280..65b8b22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,10 +17,6 @@ mod http; pub mod setup; mod socks; mod tun2proxy; -#[cfg(any(target_os = "linux", target_os = "android"))] -mod tuntapinterface; -#[cfg(any(target_os = "linux", target_os = "android"))] -mod tuntapinterfacedesc; mod virtdevice; mod virtdns; #[cfg(target_os = "windows")] diff --git a/src/tun2proxy.rs b/src/tun2proxy.rs index 9abf7c6..0e17ef6 100644 --- a/src/tun2proxy.rs +++ b/src/tun2proxy.rs @@ -1,17 +1,15 @@ #![allow(dead_code)] -#[cfg(any(target_os = "linux", target_os = "android"))] -use crate::tuntapinterface::TunTapInterface; +#[cfg(target_os = "windows")] +use crate::wintuninterface::{NamedPipeSource, WinTunInterface}; use crate::{dns, error::Error, error::Result, virtdevice::VirtualTunDevice, NetworkInterface, Options}; #[cfg(target_family = "unix")] use mio::unix::SourceFd; use mio::{event::Event, net::TcpStream, net::UdpSocket, Events, Interest, Poll, Token}; #[cfg(any(target_os = "macos", target_os = "ios"))] use smoltcp::phy::RawSocket; -// #[cfg(any(target_os = "linux", target_os = "android"))] -// use smoltcp::phy::TunTapInterface; -#[cfg(target_os = "windows")] -use crate::wintuninterface::{NamedPipeSource, WinTunInterface}; +#[cfg(any(target_os = "linux", target_os = "android"))] +use smoltcp::phy::TunTapInterface; use smoltcp::{ iface::{Config, Interface, SocketHandle, SocketSet}, phy::{Device, Medium, RxToken, TxToken}, diff --git a/src/tuntapinterface.rs b/src/tuntapinterface.rs deleted file mode 100644 index 10710f9..0000000 --- a/src/tuntapinterface.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::tuntapinterfacedesc::TunTapInterfaceDesc; -use smoltcp::{ - phy::{self, Device, DeviceCapabilities, Medium}, - time::Instant, -}; -use std::{ - cell::RefCell, - io, - os::unix::io::{AsRawFd, RawFd}, - rc::Rc, - vec::Vec, -}; - -/// A virtual TUN (IP) or TAP (Ethernet) interface. -#[derive(Debug)] -pub struct TunTapInterface { - lower: Rc>, - mtu: usize, - medium: Medium, -} - -impl AsRawFd for TunTapInterface { - fn as_raw_fd(&self) -> RawFd { - self.lower.borrow().as_raw_fd() - } -} - -impl TunTapInterface { - /// Attaches to a TUN/TAP interface called `name`, or creates it if it does not exist. - /// - /// If `name` is a persistent interface configured with UID of the current user, - /// no special privileges are needed. Otherwise, this requires superuser privileges - /// or a corresponding capability set on the executable. - pub fn new(name: &str, medium: Medium) -> io::Result { - let lower = TunTapInterfaceDesc::new(name, medium)?; - let mtu = lower.interface_mtu()?; - Ok(TunTapInterface { - lower: Rc::new(RefCell::new(lower)), - mtu, - medium, - }) - } - - /// Attaches to a TUN/TAP interface specified by file descriptor `fd`. - /// - /// On platforms like Android, a file descriptor to a tun interface is exposed. - /// On these platforms, a TunTapInterface cannot be instantiated with a name. - pub fn from_fd(fd: RawFd, medium: Medium, mtu: usize) -> io::Result { - let lower = TunTapInterfaceDesc::from_fd(fd, mtu)?; - Ok(TunTapInterface { - lower: Rc::new(RefCell::new(lower)), - mtu, - medium, - }) - } -} - -impl Device for TunTapInterface { - type RxToken<'a> = RxToken; - type TxToken<'a> = TxToken; - - fn capabilities(&self) -> DeviceCapabilities { - let mut v = DeviceCapabilities::default(); - v.max_transmission_unit = self.mtu; - v.medium = self.medium; - v - } - - fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let mut lower = self.lower.borrow_mut(); - let mut buffer = vec![0; self.mtu]; - match lower.recv(&mut buffer[..]) { - Ok(size) => { - buffer.resize(size, 0); - let rx = RxToken { buffer }; - let tx = TxToken { - lower: self.lower.clone(), - }; - Some((rx, tx)) - } - Err(err) if err.kind() == io::ErrorKind::WouldBlock => None, - Err(err) => panic!("{}", err), - } - } - - fn transmit(&mut self, _timestamp: Instant) -> Option> { - Some(TxToken { - lower: self.lower.clone(), - }) - } -} - -#[doc(hidden)] -pub struct RxToken { - buffer: Vec, -} - -impl phy::RxToken for RxToken { - fn consume(mut self, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - f(&mut self.buffer[..]) - } -} - -#[doc(hidden)] -pub struct TxToken { - lower: Rc>, -} - -impl phy::TxToken for TxToken { - fn consume(self, len: usize, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - let mut lower = self.lower.borrow_mut(); - let mut buffer = vec![0; len]; - let result = f(&mut buffer); - match lower.send(&buffer[..]) { - Ok(_) => {} - Err(err) if err.kind() == io::ErrorKind::WouldBlock => { - log::error!("phy: tx failed due to WouldBlock") - } - Err(err) => panic!("{}", err), - } - result - } -} diff --git a/src/tuntapinterfacedesc.rs b/src/tuntapinterfacedesc.rs deleted file mode 100644 index 75ea2ce..0000000 --- a/src/tuntapinterfacedesc.rs +++ /dev/null @@ -1,154 +0,0 @@ -use smoltcp::{phy::Medium, wire::EthernetFrame}; -use std::{ - io, - os::unix::io::{AsRawFd, RawFd}, -}; - -#[derive(Debug)] -pub struct TunTapInterfaceDesc { - lower: libc::c_int, - mtu: usize, -} - -impl AsRawFd for TunTapInterfaceDesc { - fn as_raw_fd(&self) -> RawFd { - self.lower - } -} - -impl TunTapInterfaceDesc { - pub fn new(name: &str, medium: Medium) -> io::Result { - let lower = unsafe { - let lower = libc::open( - "/dev/net/tun\0".as_ptr() as *const libc::c_char, - libc::O_RDWR | libc::O_NONBLOCK, - ); - if lower == -1 { - return Err(io::Error::last_os_error()); - } - lower - }; - - let mut ifreq = ifreq_for(name); - Self::attach_interface_ifreq(lower, medium, &mut ifreq)?; - let mtu = Self::mtu_ifreq(medium, &mut ifreq)?; - - Ok(TunTapInterfaceDesc { lower, mtu }) - } - - pub fn from_fd(fd: RawFd, mtu: usize) -> io::Result { - Ok(TunTapInterfaceDesc { lower: fd, mtu }) - } - - fn attach_interface_ifreq(lower: libc::c_int, medium: Medium, ifr: &mut Ifreq) -> io::Result<()> { - let mode = match medium { - Medium::Ip => imp::IFF_TUN, - Medium::Ethernet => imp::IFF_TAP, - Medium::Ieee802154 => todo!(), - }; - ifr.ifr_data = mode | imp::IFF_NO_PI; - ifreq_ioctl(lower, ifr, imp::TUNSETIFF).map(|_| ()) - } - - fn mtu_ifreq(medium: Medium, ifr: &mut Ifreq) -> io::Result { - let lower = unsafe { - let lower = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); - if lower == -1 { - return Err(io::Error::last_os_error()); - } - lower - }; - - let ip_mtu = ifreq_ioctl(lower, ifr, imp::SIOCGIFMTU).map(|mtu| mtu as usize); - - unsafe { - libc::close(lower); - } - - // Propagate error after close, to ensure we always close. - let ip_mtu = ip_mtu?; - - // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) - // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. - let mtu = match medium { - Medium::Ip => ip_mtu, - Medium::Ethernet => ip_mtu + EthernetFrame::<&[u8]>::header_len(), - Medium::Ieee802154 => todo!(), - }; - - Ok(mtu) - } - - pub fn interface_mtu(&self) -> io::Result { - Ok(self.mtu) - } - - pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result { - unsafe { - let len = libc::read(self.lower, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len()); - if len == -1 { - return Err(io::Error::last_os_error()); - } - Ok(len as usize) - } - } - - pub fn send(&mut self, buffer: &[u8]) -> io::Result { - unsafe { - let len = libc::write(self.lower, buffer.as_ptr() as *const libc::c_void, buffer.len()); - if len == -1 { - return Err(io::Error::last_os_error()); - } - Ok(len as usize) - } - } -} - -impl Drop for TunTapInterfaceDesc { - fn drop(&mut self) { - unsafe { - libc::close(self.lower); - } - } -} - -#[repr(C)] -#[derive(Debug)] -struct Ifreq { - ifr_name: [libc::c_char; libc::IF_NAMESIZE], - ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ -} - -fn ifreq_for(name: &str) -> Ifreq { - let mut ifreq = Ifreq { - ifr_name: [0; libc::IF_NAMESIZE], - ifr_data: 0, - }; - for (i, byte) in name.as_bytes().iter().enumerate() { - ifreq.ifr_name[i] = *byte as libc::c_char - } - ifreq -} - -fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut Ifreq, cmd: libc::c_ulong) -> io::Result { - unsafe { - let res = libc::ioctl(lower, cmd as _, ifreq as *mut Ifreq); - if res == -1 { - return Err(io::Error::last_os_error()); - } - } - - Ok(ifreq.ifr_data) -} - -mod imp { - pub const SIOCGIFMTU: libc::c_ulong = 0x8921; - // pub const SIOCGIFINDEX: libc::c_ulong = 0x8933; - // pub const ETH_P_ALL: libc::c_short = 0x0003; - // pub const ETH_P_IEEE802154: libc::c_short = 0x00F6; - - pub const TUNSETIFF: libc::c_ulong = 0x400454CA; - pub const IFF_TUN: libc::c_int = 0x0001; - pub const IFF_TAP: libc::c_int = 0x0002; - pub const IFF_NO_PI: libc::c_int = 0x1000; -}