tun2/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_NAPI, IFF_NO_PI, IFF_RUNNING,
17    IFF_TAP, IFF_TUN, IFF_UP, IFF_VNET_HDR, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
18};
19use std::{
20    ffi::{CStr, CString},
21    io::{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        if let Some(fd) = config.raw_fd {
61            let close_fd_on_drop = config.close_fd_on_drop.unwrap_or(true);
62            let tun_fd = Fd::new(fd, close_fd_on_drop)?;
63            let mtu = config.mtu.unwrap_or(crate::DEFAULT_MTU);
64            let packet_information = config.platform_config.packet_information;
65            let tun_name = config.tun_name.clone().unwrap_or_else(|| "".into());
66            let ctl = Fd::new(unsafe { libc::socket(AF_INET, SOCK_DGRAM, 0) }, true)?;
67            return Ok(Device {
68                tun: Tun::new(tun_fd, mtu, packet_information),
69                tun_name,
70                ctl,
71            });
72        }
73
74        let mut device = unsafe {
75            let dev_name = match config.tun_name.as_ref() {
76                Some(tun_name) => {
77                    let tun_name = CString::new(tun_name.clone())?;
78
79                    if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
80                        return Err(Error::NameTooLong);
81                    }
82
83                    Some(tun_name)
84                }
85
86                None => None,
87            };
88
89            let mut req: ifreq = mem::zeroed();
90
91            if let Some(dev_name) = dev_name.as_ref() {
92                ptr::copy_nonoverlapping(
93                    dev_name.as_ptr() as *const c_char,
94                    req.ifr_name.as_mut_ptr(),
95                    dev_name.as_bytes_with_nul().len(),
96                );
97            }
98
99            let device_type: c_short = config.layer.unwrap_or(Layer::L3).into();
100
101            let queues_num = config.queues.unwrap_or(1);
102            if queues_num != 1 {
103                return Err(Error::InvalidQueuesNumber);
104            }
105
106            let iff_no_pi = IFF_NO_PI as c_short;
107            let iff_multi_queue = IFF_MULTI_QUEUE as c_short;
108            let iff_napi = IFF_NAPI as c_short;
109            let iff_vnet_hdr = IFF_VNET_HDR as c_short;
110            let packet_information = config.platform_config.packet_information;
111            let napi = config.platform_config.napi;
112            let vnet_hdr = config.platform_config.vnet_hdr;
113            req.ifr_ifru.ifru_flags = device_type
114                | if packet_information { 0 } else { iff_no_pi }
115                | if napi { iff_napi } else { 0 }
116                | if vnet_hdr { iff_vnet_hdr } else { 0 }
117                | if queues_num > 1 { iff_multi_queue } else { 0 };
118
119            let tun_fd = {
120                let fd = libc::open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR);
121                let tun_fd = Fd::new(fd, true).map_err(|_| std::io::Error::last_os_error())?;
122
123                if let Err(err) = tunsetiff(tun_fd.inner, &mut req as *mut _ as *mut _) {
124                    return Err(std::io::Error::from(err).into());
125                }
126
127                tun_fd
128            };
129
130            let mtu = config.mtu.unwrap_or(crate::DEFAULT_MTU);
131
132            let ctl = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0), true)?;
133
134            let tun_name = CStr::from_ptr(req.ifr_name.as_ptr())
135                .to_string_lossy()
136                .to_string();
137            Device {
138                tun_name,
139                tun: Tun::new(tun_fd, mtu, packet_information),
140                ctl,
141            }
142        };
143
144        if config.platform_config.ensure_root_privileges {
145            device.configure(config)?;
146        }
147
148        Ok(device)
149    }
150
151    /// Prepare a new request.
152    unsafe fn request(&self) -> ifreq {
153        let mut req: ifreq = mem::zeroed();
154        ptr::copy_nonoverlapping(
155            self.tun_name.as_ptr() as *const c_char,
156            req.ifr_name.as_mut_ptr(),
157            self.tun_name.len(),
158        );
159
160        req
161    }
162
163    /// Make the device persistent.
164    pub fn persist(&mut self) -> Result<()> {
165        unsafe {
166            if let Err(err) = tunsetpersist(self.as_raw_fd(), &1) {
167                Err(std::io::Error::from(err).into())
168            } else {
169                Ok(())
170            }
171        }
172    }
173
174    /// Set the owner of the device.
175    pub fn user(&mut self, value: i32) -> Result<()> {
176        unsafe {
177            if let Err(err) = tunsetowner(self.as_raw_fd(), &value) {
178                Err(std::io::Error::from(err).into())
179            } else {
180                Ok(())
181            }
182        }
183    }
184
185    /// Set the group of the device.
186    pub fn group(&mut self, value: i32) -> Result<()> {
187        unsafe {
188            if let Err(err) = tunsetgroup(self.as_raw_fd(), &value) {
189                Err(std::io::Error::from(err).into())
190            } else {
191                Ok(())
192            }
193        }
194    }
195
196    /// Split the interface into a `Reader` and `Writer`.
197    pub fn split(self) -> (posix::Reader, posix::Writer) {
198        (self.tun.reader, self.tun.writer)
199    }
200
201    /// Set non-blocking mode
202    pub fn set_nonblock(&self) -> std::io::Result<()> {
203        self.tun.set_nonblock()
204    }
205
206    /// Recv a packet from tun device
207    pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
208        self.tun.recv(buf)
209    }
210
211    /// Send a packet to tun device
212    pub fn send(&self, buf: &[u8]) -> std::io::Result<usize> {
213        self.tun.send(buf)
214    }
215}
216
217impl Read for Device {
218    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
219        self.tun.read(buf)
220    }
221
222    fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
223        self.tun.read_vectored(bufs)
224    }
225}
226
227impl Write for Device {
228    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
229        self.tun.write(buf)
230    }
231
232    fn flush(&mut self) -> std::io::Result<()> {
233        self.tun.flush()
234    }
235
236    fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
237        self.tun.write_vectored(bufs)
238    }
239}
240
241impl AbstractDevice for Device {
242    fn tun_index(&self) -> Result<i32> {
243        let name = self.tun_name()?;
244        Ok(posix::tun_name_to_index(name)? as i32)
245    }
246
247    fn tun_name(&self) -> Result<String> {
248        Ok(self.tun_name.clone())
249    }
250
251    fn set_tun_name(&mut self, value: &str) -> Result<()> {
252        unsafe {
253            let tun_name = CString::new(value)?;
254
255            if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
256                return Err(Error::NameTooLong);
257            }
258
259            let mut req = self.request();
260            ptr::copy_nonoverlapping(
261                tun_name.as_ptr() as *const c_char,
262                req.ifr_ifru.ifru_newname.as_mut_ptr(),
263                value.len(),
264            );
265
266            if let Err(err) = siocsifname(self.ctl.as_raw_fd(), &req) {
267                return Err(std::io::Error::from(err).into());
268            }
269
270            self.tun_name = value.into();
271
272            Ok(())
273        }
274    }
275
276    fn enabled(&mut self, value: bool) -> Result<()> {
277        unsafe {
278            let mut req = self.request();
279
280            if let Err(err) = siocgifflags(self.ctl.as_raw_fd(), &mut req) {
281                return Err(std::io::Error::from(err).into());
282            }
283
284            if value {
285                req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short;
286            } else {
287                req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short);
288            }
289
290            if let Err(err) = siocsifflags(self.ctl.as_raw_fd(), &req) {
291                return Err(std::io::Error::from(err).into());
292            }
293
294            Ok(())
295        }
296    }
297
298    fn address(&self) -> Result<IpAddr> {
299        unsafe {
300            let mut req = self.request();
301            if let Err(err) = siocgifaddr(self.ctl.as_raw_fd(), &mut req) {
302                return Err(std::io::Error::from(err).into());
303            }
304            let sa = sockaddr_union::from(req.ifr_ifru.ifru_addr);
305            Ok(std::net::SocketAddr::try_from(sa)?.ip())
306        }
307    }
308
309    fn set_address(&mut self, value: IpAddr) -> Result<()> {
310        unsafe {
311            let mut req = self.request();
312            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_addr, OVERWRITE_SIZE);
313            if let Err(err) = siocsifaddr(self.ctl.as_raw_fd(), &req) {
314                return Err(std::io::Error::from(err).into());
315            }
316            Ok(())
317        }
318    }
319
320    fn destination(&self) -> Result<IpAddr> {
321        unsafe {
322            let mut req = self.request();
323            if let Err(err) = siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) {
324                return Err(std::io::Error::from(err).into());
325            }
326            let sa = sockaddr_union::from(req.ifr_ifru.ifru_dstaddr);
327            Ok(std::net::SocketAddr::try_from(sa)?.ip())
328        }
329    }
330
331    fn set_destination(&mut self, value: IpAddr) -> Result<()> {
332        unsafe {
333            let mut req = self.request();
334            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_dstaddr, OVERWRITE_SIZE);
335            if let Err(err) = siocsifdstaddr(self.ctl.as_raw_fd(), &req) {
336                return Err(std::io::Error::from(err).into());
337            }
338            Ok(())
339        }
340    }
341
342    fn broadcast(&self) -> Result<IpAddr> {
343        unsafe {
344            let mut req = self.request();
345            if let Err(err) = siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) {
346                return Err(std::io::Error::from(err).into());
347            }
348            let sa = sockaddr_union::from(req.ifr_ifru.ifru_broadaddr);
349            Ok(std::net::SocketAddr::try_from(sa)?.ip())
350        }
351    }
352
353    fn set_broadcast(&mut self, value: IpAddr) -> Result<()> {
354        unsafe {
355            let mut req = self.request();
356            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_broadaddr, OVERWRITE_SIZE);
357            if let Err(err) = siocsifbrdaddr(self.ctl.as_raw_fd(), &req) {
358                return Err(std::io::Error::from(err).into());
359            }
360            Ok(())
361        }
362    }
363
364    fn netmask(&self) -> Result<IpAddr> {
365        unsafe {
366            let mut req = self.request();
367            if let Err(err) = siocgifnetmask(self.ctl.as_raw_fd(), &mut req) {
368                return Err(std::io::Error::from(err).into());
369            }
370            let sa = sockaddr_union::from(req.ifr_ifru.ifru_netmask);
371            Ok(std::net::SocketAddr::try_from(sa)?.ip())
372        }
373    }
374
375    fn set_netmask(&mut self, value: IpAddr) -> Result<()> {
376        unsafe {
377            let mut req = self.request();
378            ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_netmask, OVERWRITE_SIZE);
379            if let Err(err) = siocsifnetmask(self.ctl.as_raw_fd(), &req) {
380                return Err(std::io::Error::from(err).into());
381            }
382            Ok(())
383        }
384    }
385
386    fn mtu(&self) -> Result<u16> {
387        unsafe {
388            let mut req = self.request();
389
390            if let Err(err) = siocgifmtu(self.ctl.as_raw_fd(), &mut req) {
391                return Err(std::io::Error::from(err).into());
392            }
393
394            req.ifr_ifru
395                .ifru_mtu
396                .try_into()
397                .map_err(|_| Error::TryFromIntError)
398        }
399    }
400
401    fn set_mtu(&mut self, value: u16) -> Result<()> {
402        unsafe {
403            let mut req = self.request();
404            req.ifr_ifru.ifru_mtu = value as i32;
405
406            if let Err(err) = siocsifmtu(self.ctl.as_raw_fd(), &req) {
407                return Err(std::io::Error::from(err).into());
408            }
409            self.tun.set_mtu(value);
410            Ok(())
411        }
412    }
413
414    fn packet_information(&self) -> bool {
415        self.tun.packet_information()
416    }
417}
418
419impl AsRawFd for Device {
420    fn as_raw_fd(&self) -> RawFd {
421        self.tun.as_raw_fd()
422    }
423}
424
425impl IntoRawFd for Device {
426    fn into_raw_fd(self) -> RawFd {
427        self.tun.into_raw_fd()
428    }
429}
430
431impl From<Layer> for c_short {
432    fn from(layer: Layer) -> Self {
433        match layer {
434            Layer::L2 => IFF_TAP as c_short,
435            Layer::L3 => IFF_TUN as c_short,
436        }
437    }
438}