1#[cfg(target_os = "linux")]
2use crate::linux::interface::Interface;
3#[cfg(target_os = "linux")]
4use crate::linux::params::Params;
5use crate::result::Result;
6use async_std::fs::File;
7use async_std::fs::OpenOptions;
8use async_std::io::{BufReader, BufWriter};
9#[cfg(target_family = "unix")]
10use async_std::os::unix::io::{AsRawFd, RawFd};
11use async_std::sync::Arc;
12use mac_address::{mac_address_by_name, MacAddress};
13use std::net::Ipv4Addr;
14
15pub struct Tun {
17 file: File,
18 iface: Arc<Interface>,
19}
20
21impl Tun {
22 #[cfg(target_os = "linux")]
23 async fn alloc(params: Params, queues: usize) -> Result<(Vec<File>, Interface)> {
24 let mut files = Vec::with_capacity(queues);
25 for _ in 0..queues {
26 files.push(
27 OpenOptions::new()
28 .read(true)
29 .write(true)
30 .open("/dev/net/tun")
31 .await?,
32 );
33 }
34 let iface = Interface::new(
35 files.iter().map(|file| file.as_raw_fd()).collect(),
36 params.name.as_deref().unwrap_or_default(),
37 params.flags,
38 )?;
39 if let Some(mtu) = params.mtu {
40 iface.mtu(Some(mtu))?;
41 }
42 if let Some(owner) = params.owner {
43 iface.owner(owner)?;
44 }
45 if let Some(group) = params.group {
46 iface.group(group)?;
47 }
48 if let Some(address) = params.address {
49 iface.address(Some(address))?;
50 }
51 if let Some(netmask) = params.netmask {
52 iface.netmask(Some(netmask))?;
53 }
54 if let Some(destination) = params.destination {
55 iface.destination(Some(destination))?;
56 }
57 if let Some(broadcast) = params.broadcast {
58 iface.broadcast(Some(broadcast))?;
59 }
60 if let Some(mac) = params.mac {
61 iface.set_mac(mac)?;
62 }
63 if params.persist {
64 iface.persist()?;
65 }
66 if params.up {
67 iface.flags(Some(libc::IFF_UP as i16 | libc::IFF_RUNNING as i16))?;
68 }
69 Ok((files, iface))
70 }
71
72 #[cfg(not(any(target_os = "linux")))]
73 async fn alloc(params: Params) -> Result<Self> {
74 unimplemented!()
75 }
76
77 pub(crate) async fn new(params: Params) -> Result<Self> {
79 let (files, iface) = Self::alloc(params, 1).await?;
80 let file = files.into_iter().next().unwrap();
81 Ok(Self {
82 file,
83 iface: Arc::new(iface),
84 })
85 }
86
87 #[cfg(target_os = "linux")]
89 pub(crate) async fn new_mq(params: Params, queues: usize) -> Result<Vec<Self>> {
90 let (files, iface) = Self::alloc(params, queues).await?;
91 let mut tuns = Vec::with_capacity(queues);
92 let iface = Arc::new(iface);
93 for file in files.into_iter() {
94 tuns.push(Self {
95 file,
96 iface: iface.clone(),
97 })
98 }
99 Ok(tuns)
100 }
101
102 pub fn name(&self) -> &str {
104 self.iface.name()
105 }
106
107 pub fn mtu(&self) -> Result<i32> {
109 self.iface.mtu(None)
110 }
111
112 pub fn address(&self) -> Result<Ipv4Addr> {
114 self.iface.address(None)
115 }
116
117 pub fn destination(&self) -> Result<Ipv4Addr> {
119 self.iface.destination(None)
120 }
121
122 pub fn broadcast(&self) -> Result<Ipv4Addr> {
124 self.iface.broadcast(None)
125 }
126
127 pub fn netmask(&self) -> Result<Ipv4Addr> {
129 self.iface.netmask(None)
130 }
131
132 pub fn mac(&self) -> Result<Option<MacAddress>> {
134 Ok(mac_address_by_name(self.name())?)
135 }
136
137 pub fn flags(&self) -> Result<i16> {
139 self.iface.flags(None)
140 }
141
142 pub fn split(&self) -> (BufReader<&File>, BufWriter<&File>) {
144 (BufReader::new(&self.file), BufWriter::new(&self.file))
145 }
146
147 pub fn reader(&self) -> BufReader<&File> {
149 BufReader::new(&self.file)
150 }
151
152 pub fn writer(&self) -> BufWriter<&File> {
154 BufWriter::new(&self.file)
155 }
156}
157
158#[cfg(target_family = "unix")]
159impl AsRawFd for Tun {
160 fn as_raw_fd(&self) -> RawFd {
161 self.file.as_raw_fd()
162 }
163}