tun_easytier/platform/linux/
device.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use libc::{
16    self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NO_PI, IFF_RUNNING, IFF_TAP,
17    IFF_TUN, IFF_UP, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
18};
19use std::{
20    ffi::{CStr, CString},
21    io::{self, Read, Write},
22    mem,
23    net::IpAddr,
24    os::unix::io::{AsRawFd, IntoRawFd, RawFd},
25    ptr,
26};
27
28use crate::{
29    configuration::{Configuration, Layer},
30    device::AbstractDevice,
31    error::{Error, Result},
32    platform::linux::sys::*,
33    platform::posix::{self, ipaddr_to_sockaddr, sockaddr_union, Fd, Tun},
34};
35
36const OVERWRITE_SIZE: usize = std::mem::size_of::<libc::__c_anonymous_ifr_ifru>();
37
38/// A TUN device using the TUN/TAP Linux driver.
39pub struct Device {
40    tun_name: String,
41    tun: Tun,
42    ctl: Fd,
43}
44
45impl AsRef<dyn AbstractDevice + 'static> for Device {
46    fn as_ref(&self) -> &(dyn AbstractDevice + 'static) {
47        self
48    }
49}
50
51impl AsMut<dyn AbstractDevice + 'static> for Device {
52    fn as_mut(&mut self) -> &mut (dyn AbstractDevice + 'static) {
53        self
54    }
55}
56
57impl Device {
58    /// Create a new `Device` for the given `Configuration`.
59    pub fn new(config: &Configuration) -> Result<Self> {
60        let mut device = unsafe {
61            if config.raw_fd.is_some() {
62                // TODO: Should we support this in the future?
63                return Err(Error::NotImplemented);
64            }
65            let dev_name = match config.tun_name.as_ref() {
66                Some(tun_name) => {
67                    let tun_name = CString::new(tun_name.clone())?;
68
69                    if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
70                        return Err(Error::NameTooLong);
71                    }
72
73                    Some(tun_name)
74                }
75
76                None => None,
77            };
78
79            let mut req: ifreq = mem::zeroed();
80
81            if let Some(dev_name) = dev_name.as_ref() {
82                ptr::copy_nonoverlapping(
83                    dev_name.as_ptr() as *const c_char,
84                    req.ifr_name.as_mut_ptr(),
85                    dev_name.as_bytes_with_nul().len(),
86                );
87            }
88
89            let device_type: c_short = config.layer.unwrap_or(Layer::L3).into();
90
91            let queues_num = config.queues.unwrap_or(1);
92            if queues_num != 1 {
93                return Err(Error::InvalidQueuesNumber);
94            }
95
96            let iff_no_pi = IFF_NO_PI as c_short;
97            let iff_multi_queue = IFF_MULTI_QUEUE as c_short;
98            let packet_information = config.platform_config.packet_information;
99            req.ifr_ifru.ifru_flags = device_type
100                | if packet_information { 0 } else { iff_no_pi }
101                | if queues_num > 1 { iff_multi_queue } else { 0 };
102
103            let tun_fd = {
104                let fd = libc::open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR);
105                let tun_fd = Fd::new(fd, true).map_err(|_| io::Error::last_os_error())?;
106
107                if let Err(err) = tunsetiff(tun_fd.inner, &mut req as *mut _ as *mut _) {
108                    return Err(io::Error::from(err).into());
109                }
110
111                tun_fd
112            };
113
114            let mtu = config.mtu.unwrap_or(crate::DEFAULT_MTU);
115
116            let ctl = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0), true)?;
117
118            let tun_name = CStr::from_ptr(req.ifr_name.as_ptr())
119                .to_string_lossy()
120                .to_string();
121            Device {
122                tun_name,
123                tun: Tun::new(tun_fd, mtu, packet_information),
124                ctl,
125            }
126        };
127
128        if config.platform_config.ensure_root_privileges {
129            device.configure(config)?;
130        }
131
132        Ok(device)
133    }
134
135    /// Prepare a new request.
136    unsafe fn request(&self) -> ifreq {
137        let mut req: ifreq = mem::zeroed();
138        ptr::copy_nonoverlapping(
139            self.tun_name.as_ptr() as *const c_char,
140            req.ifr_name.as_mut_ptr(),
141            self.tun_name.len(),
142        );
143
144        req
145    }
146
147    /// Make the device persistent.
148    pub fn persist(&mut self) -> Result<()> {
149        unsafe {
150            if let Err(err) = tunsetpersist(self.as_raw_fd(), &1) {
151                Err(io::Error::from(err).into())
152            } else {
153                Ok(())
154            }
155        }
156    }
157
158    /// Set the owner of the device.
159    pub fn user(&mut self, value: i32) -> Result<()> {
160        unsafe {
161            if let Err(err) = tunsetowner(self.as_raw_fd(), &value) {
162                Err(io::Error::from(err).into())
163            } else {
164                Ok(())
165            }
166        }
167    }
168
169    /// Set the group of the device.
170    pub fn group(&mut self, value: i32) -> Result<()> {
171        unsafe {
172            if let Err(err) = tunsetgroup(self.as_raw_fd(), &value) {
173                Err(io::Error::from(err).into())
174            } else {
175                Ok(())
176            }
177        }
178    }
179
180    /// Split the interface into a `Reader` and `Writer`.
181    pub fn split(self) -> (posix::Reader, posix::Writer) {
182        (self.tun.reader, self.tun.writer)
183    }
184
185    /// Set non-blocking mode
186    pub fn set_nonblock(&self) -> io::Result<()> {
187        self.tun.set_nonblock()
188    }
189
190    /// Recv a packet from tun device
191    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
192        self.tun.recv(buf)
193    }
194
195    /// Send a packet to tun device
196    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
197        self.tun.send(buf)
198    }
199}
200
201impl Read for Device {
202    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
203        self.tun.read(buf)
204    }
205
206    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
207        self.tun.read_vectored(bufs)
208    }
209}
210
211impl Write for Device {
212    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
213        self.tun.write(buf)
214    }
215
216    fn flush(&mut self) -> io::Result<()> {
217        self.tun.flush()
218    }
219
220    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
221        self.tun.write_vectored(bufs)
222    }
223}
224
225impl AbstractDevice for Device {
226    fn tun_name(&self) -> Result<String> {
227        Ok(self.tun_name.clone())
228    }
229
230    fn set_tun_name(&mut self, value: &str) -> Result<()> {
231        unsafe {
232            let tun_name = CString::new(value)?;
233
234            if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
235                return Err(Error::NameTooLong);
236            }
237
238            let mut req = self.request();
239            ptr::copy_nonoverlapping(
240                tun_name.as_ptr() as *const c_char,
241                req.ifr_ifru.ifru_newname.as_mut_ptr(),
242                value.len(),
243            );
244
245            if let Err(err) = siocsifname(self.ctl.as_raw_fd(), &req) {
246                return Err(io::Error::from(err).into());
247            }
248
249            self.tun_name = value.into();
250
251            Ok(())
252        }
253    }
254
255    fn enabled(&mut self, value: bool) -> Result<()> {
256        unsafe {
257            let mut req = self.request();
258
259            if let Err(err) = siocgifflags(self.ctl.as_raw_fd(), &mut req) {
260                return Err(io::Error::from(err).into());
261            }
262
263            if value {
264                req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short;
265            } else {
266                req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short);
267            }
268
269            if let Err(err) = siocsifflags(self.ctl.as_raw_fd(), &req) {
270                return Err(io::Error::from(err).into());
271            }
272
273            Ok(())
274        }
275    }
276
277    fn address(&self) -> Result<IpAddr> {
278        unsafe {
279            let mut req = self.request();
280            if let Err(err) = siocgifaddr(self.ctl.as_raw_fd(), &mut req) {
281                return Err(io::Error::from(err).into());
282            }
283            let sa = sockaddr_union::from(req.ifr_ifru.ifru_addr);
284            Ok(std::net::SocketAddr::try_from(sa)?.ip())
285        }
286    }
287
288    fn set_address(&mut self, value: IpAddr) -> Result<()> {
289        unsafe {
290            let mut req = self.request();
291            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_addr, OVERWRITE_SIZE);
292            if let Err(err) = siocsifaddr(self.ctl.as_raw_fd(), &req) {
293                return Err(io::Error::from(err).into());
294            }
295            Ok(())
296        }
297    }
298
299    fn destination(&self) -> Result<IpAddr> {
300        unsafe {
301            let mut req = self.request();
302            if let Err(err) = siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) {
303                return Err(io::Error::from(err).into());
304            }
305            let sa = sockaddr_union::from(req.ifr_ifru.ifru_dstaddr);
306            Ok(std::net::SocketAddr::try_from(sa)?.ip())
307        }
308    }
309
310    fn set_destination(&mut self, value: IpAddr) -> Result<()> {
311        unsafe {
312            let mut req = self.request();
313            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_dstaddr, OVERWRITE_SIZE);
314            if let Err(err) = siocsifdstaddr(self.ctl.as_raw_fd(), &req) {
315                return Err(io::Error::from(err).into());
316            }
317            Ok(())
318        }
319    }
320
321    fn broadcast(&self) -> Result<IpAddr> {
322        unsafe {
323            let mut req = self.request();
324            if let Err(err) = siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) {
325                return Err(io::Error::from(err).into());
326            }
327            let sa = sockaddr_union::from(req.ifr_ifru.ifru_broadaddr);
328            Ok(std::net::SocketAddr::try_from(sa)?.ip())
329        }
330    }
331
332    fn set_broadcast(&mut self, value: IpAddr) -> Result<()> {
333        unsafe {
334            let mut req = self.request();
335            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_broadaddr, OVERWRITE_SIZE);
336            if let Err(err) = siocsifbrdaddr(self.ctl.as_raw_fd(), &req) {
337                return Err(io::Error::from(err).into());
338            }
339            Ok(())
340        }
341    }
342
343    fn netmask(&self) -> Result<IpAddr> {
344        unsafe {
345            let mut req = self.request();
346            if let Err(err) = siocgifnetmask(self.ctl.as_raw_fd(), &mut req) {
347                return Err(io::Error::from(err).into());
348            }
349            let sa = sockaddr_union::from(req.ifr_ifru.ifru_netmask);
350            Ok(std::net::SocketAddr::try_from(sa)?.ip())
351        }
352    }
353
354    fn set_netmask(&mut self, value: IpAddr) -> Result<()> {
355        unsafe {
356            let mut req = self.request();
357            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_netmask, OVERWRITE_SIZE);
358            if let Err(err) = siocsifnetmask(self.ctl.as_raw_fd(), &req) {
359                return Err(io::Error::from(err).into());
360            }
361            Ok(())
362        }
363    }
364
365    fn mtu(&self) -> Result<u16> {
366        unsafe {
367            let mut req = self.request();
368
369            if let Err(err) = siocgifmtu(self.ctl.as_raw_fd(), &mut req) {
370                return Err(io::Error::from(err).into());
371            }
372
373            req.ifr_ifru
374                .ifru_mtu
375                .try_into()
376                .map_err(|_| Error::TryFromIntError)
377        }
378    }
379
380    fn set_mtu(&mut self, value: u16) -> Result<()> {
381        unsafe {
382            let mut req = self.request();
383            req.ifr_ifru.ifru_mtu = value as i32;
384
385            if let Err(err) = siocsifmtu(self.ctl.as_raw_fd(), &req) {
386                return Err(io::Error::from(err).into());
387            }
388            self.tun.set_mtu(value);
389            Ok(())
390        }
391    }
392
393    fn packet_information(&self) -> bool {
394        self.tun.packet_information()
395    }
396}
397
398impl AsRawFd for Device {
399    fn as_raw_fd(&self) -> RawFd {
400        self.tun.as_raw_fd()
401    }
402}
403
404impl IntoRawFd for Device {
405    fn into_raw_fd(self) -> RawFd {
406        self.tun.into_raw_fd()
407    }
408}
409
410impl From<Layer> for c_short {
411    fn from(layer: Layer) -> Self {
412        match layer {
413            Layer::L2 => IFF_TAP as c_short,
414            Layer::L3 => IFF_TUN as c_short,
415        }
416    }
417}