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