1 use std::cell::RefCell; 2 use std::io; 3 use std::os::unix::io::{AsRawFd, RawFd}; 4 use std::rc::Rc; 5 use std::vec::Vec; 6 7 use crate::phy::{self, sys, Device, DeviceCapabilities, Medium}; 8 use crate::time::Instant; 9 10 /// A virtual TUN (IP) or TAP (Ethernet) interface. 11 #[derive(Debug)] 12 pub struct TunTapInterface { 13 lower: Rc<RefCell<sys::TunTapInterfaceDesc>>, 14 mtu: usize, 15 medium: Medium, 16 } 17 18 impl AsRawFd for TunTapInterface { as_raw_fd(&self) -> RawFd19 fn as_raw_fd(&self) -> RawFd { 20 self.lower.borrow().as_raw_fd() 21 } 22 } 23 24 impl TunTapInterface { 25 /// Attaches to a TUN/TAP interface called `name`, or creates it if it does not exist. 26 /// 27 /// If `name` is a persistent interface configured with UID of the current user, 28 /// no special privileges are needed. Otherwise, this requires superuser privileges 29 /// or a corresponding capability set on the executable. new(name: &str, medium: Medium) -> io::Result<TunTapInterface>30 pub fn new(name: &str, medium: Medium) -> io::Result<TunTapInterface> { 31 let mut lower = sys::TunTapInterfaceDesc::new(name, medium)?; 32 lower.attach_interface()?; 33 let mtu = lower.interface_mtu()?; 34 Ok(TunTapInterface { 35 lower: Rc::new(RefCell::new(lower)), 36 mtu, 37 medium, 38 }) 39 } 40 } 41 42 impl Device for TunTapInterface { 43 type RxToken<'a> = RxToken; 44 type TxToken<'a> = TxToken; 45 capabilities(&self) -> DeviceCapabilities46 fn capabilities(&self) -> DeviceCapabilities { 47 DeviceCapabilities { 48 max_transmission_unit: self.mtu, 49 medium: self.medium, 50 ..DeviceCapabilities::default() 51 } 52 } 53 receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>54 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { 55 let mut lower = self.lower.borrow_mut(); 56 let mut buffer = vec![0; self.mtu]; 57 match lower.recv(&mut buffer[..]) { 58 Ok(size) => { 59 buffer.resize(size, 0); 60 let rx = RxToken { buffer }; 61 let tx = TxToken { 62 lower: self.lower.clone(), 63 }; 64 Some((rx, tx)) 65 } 66 Err(err) if err.kind() == io::ErrorKind::WouldBlock => None, 67 Err(err) => panic!("{}", err), 68 } 69 } 70 transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>>71 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> { 72 Some(TxToken { 73 lower: self.lower.clone(), 74 }) 75 } 76 } 77 78 #[doc(hidden)] 79 pub struct RxToken { 80 buffer: Vec<u8>, 81 } 82 83 impl phy::RxToken for RxToken { consume<R, F>(mut self, f: F) -> R where F: FnOnce(&mut [u8]) -> R,84 fn consume<R, F>(mut self, f: F) -> R 85 where 86 F: FnOnce(&mut [u8]) -> R, 87 { 88 f(&mut self.buffer[..]) 89 } 90 } 91 92 #[doc(hidden)] 93 pub struct TxToken { 94 lower: Rc<RefCell<sys::TunTapInterfaceDesc>>, 95 } 96 97 impl phy::TxToken for TxToken { consume<R, F>(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R,98 fn consume<R, F>(self, len: usize, f: F) -> R 99 where 100 F: FnOnce(&mut [u8]) -> R, 101 { 102 let mut lower = self.lower.borrow_mut(); 103 let mut buffer = vec![0; len]; 104 let result = f(&mut buffer); 105 match lower.send(&buffer[..]) { 106 Ok(_) => {} 107 Err(err) if err.kind() == io::ErrorKind::WouldBlock => { 108 net_debug!("phy: tx failed due to WouldBlock") 109 } 110 Err(err) => panic!("{}", err), 111 } 112 result 113 } 114 } 115