tun_driver/lib.rs
1#![doc(
2 html_root_url = "https://docs.rs/tun-tap/0.1.2/tun-tap/",
3 test(attr(deny(warnings), allow(unused_variables)))
4)]
5
6
7//! A TUN/TAP bindings for Rust.
8//!
9//! This is a basic interface to create userspace virtual network adapter.
10//!
11//! For basic usage, create an [`Iface`](struct.Iface.html) object and call the
12//! [`send`](struct.Iface.html#method.send) and [`recv`](struct.Iface.html#method.recv) methods.
13//!
14//! You can also use [`Async`](async/struct.Async.html) if you want to integrate with tokio event
15//! loop. This is configurable by a feature (it is on by default).
16//!
17//! Creating the devices requires `CAP_NETADM` privileges (most commonly done by running as root).
18//!
19//! # Known issues
20//!
21//! * It is tested only on Linux and probably doesn't work anywhere else, even though other systems
22//! have some TUN/TAP support. Reports that it works (or not) and pull request to add other
23//! sustem's support are welcome.
24//! * The [`Async`](async/struct.Async.html) interface is very minimal and will require extention
25//! for further use cases and better performance.
26//! * This doesn't support advanced usage patters, like reusing already created device or creating
27//! persistent devices. Again, pull requests are welcome.
28//! * There are no automated tests. Any idea how to test this in a reasonable way?
29
30use std::ffi::CStr;
31use std::fs::{File, OpenOptions};
32use std::io::{Error, Read, Result, Write};
33use std::os::raw::{c_char, c_int};
34use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
35
36
37pub mod async;
38
39extern "C" {
40 fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int;
41}
42
43/// The mode in which open the virtual network adapter.
44#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
45pub enum Mode {
46 /// TUN mode
47 ///
48 /// The packets returned are on the IP layer (layer 3), prefixed with 4-byte header (2 bytes
49 /// are flags, 2 bytes are the protocol inside, eg one of
50 /// <https://en.wikipedia.org/wiki/EtherType#Examples>.
51 Tun = 1,
52 /// TAP mode
53 ///
54 /// The packets are on the transport layer (layer 2), and start with ethernet frame header.
55 Tap = 2,
56}
57
58/// The virtual interface.
59///
60/// This is the main structure of the crate, representing the actual virtual interface, either in
61/// TUN or TAP mode.
62#[derive(Debug)]
63pub struct Iface {
64 fd: File,
65 mode: Mode,
66 name: String,
67}
68
69impl Iface {
70 /// Creates a new virtual interface.
71 ///
72 /// # Parameters
73 ///
74 /// * `ifname`: The requested name of the virtual device. If left empty, the kernel will
75 /// provide some reasonable, currently unused name. It also can contain `%d`, which will be
76 /// replaced by a number to ensure the name is unused. Even if it isn't empty or doesn't
77 /// contain `%d`, the actual name may be different (for example truncated to OS-dependent
78 /// length). Use [`name`](#method.name) to find out the real name.
79 /// * `mode`: In which mode to create the device.
80 ///
81 /// # Errors
82 ///
83 /// This may fail for various OS-dependent reasons. However, two most common are:
84 ///
85 /// * The name is already taken.
86 /// * The process doesn't have the needed privileges (eg. `CAP_NETADM`).
87 ///
88 /// # Examples
89 ///
90 /// ```rust,no_run
91 /// # use tun_tap::*;
92 /// let iface = Iface::new("mytun", Mode::Tun).expect("Failed to create a TUN device");
93 /// let name = iface.name();
94 /// // Configure the device ‒ set IP address on it, bring it up.
95 /// let mut buffer = vec![0; 1504]; // MTU + 4 for the header
96 /// iface.recv(&mut buffer).unwrap();
97 /// ```
98 pub fn new(ifname: &str, mode: Mode) -> Result<Self> {
99 Iface::with_options(ifname, mode, true)
100 }
101 /// Creates a new virtual interface without the prepended packet info.
102 ///
103 /// # Parameters
104 ///
105 /// * `ifname`: The requested name of the virtual device. If left empty, the kernel will
106 /// provide some reasonable, currently unused name. It also can contain `%d`, which will be
107 /// replaced by a number to ensure the name is unused. Even if it isn't empty or doesn't
108 /// contain `%d`, the actual name may be different (for example truncated to OS-dependent
109 /// length). Use [`name`](#method.name) to find out the real name.
110 /// * `mode`: In which mode to create the device.
111 ///
112 /// # Errors
113 ///
114 /// This may fail for various OS-dependent reasons. However, two most common are:
115 ///
116 /// * The name is already taken.
117 /// * The process doesn't have the needed privileges (eg. `CAP_NETADM`).
118 ///
119 /// # Examples
120 ///
121 /// ```rust,no_run
122 /// # use tun_tap::*;
123 /// let iface = Iface::without_packet_info("mytap", Mode::Tap).expect("Failed to create a TAP device");
124 /// let name = iface.name();
125 /// // Configure the device ‒ set IP address on it, bring it up.
126 /// let mut buffer = vec![0; 1500]; // MTU
127 /// iface.recv(&mut buffer).unwrap();
128 /// ```
129 pub fn without_packet_info(ifname: &str, mode: Mode) -> Result<Self> {
130 Iface::with_options(ifname, mode, false)
131 }
132
133 fn with_options(ifname: &str, mode: Mode, packet_info: bool) -> Result<Self> {
134 let fd = OpenOptions::new()
135 .read(true)
136 .write(true)
137 .open("/dev/net/tun")?;
138 // The buffer is larger than needed, but who cares… it is large enough.
139 let mut name_buffer = Vec::new();
140 name_buffer.extend_from_slice(ifname.as_bytes());
141 name_buffer.extend_from_slice(&[0; 33]);
142 let name_ptr: *mut u8 = name_buffer.as_mut_ptr();
143 let result = unsafe { tuntap_setup(fd.as_raw_fd(), name_ptr, mode as c_int, { if packet_info { 1 } else { 0 } }) };
144 if result < 0 {
145 return Err(Error::last_os_error());
146 }
147 let name = unsafe {
148 CStr::from_ptr(name_ptr as *const c_char)
149 .to_string_lossy()
150 .into_owned()
151 };
152 Ok(Iface {
153 fd,
154 mode,
155 name,
156 })
157 }
158
159 /// Returns the mode of the adapter.
160 ///
161 /// It is always the same as the one passed to [`new`](#method.new).
162 pub fn mode(&self) -> Mode {
163 self.mode
164 }
165 /// Returns the real name of the adapter.
166 ///
167 /// Use this to find out what the real name of the adapter is. The parameter of
168 /// [`new`](#method.new) is more of a wish than hard requirement and the name of the created
169 /// device might be different. Therefore, always create the interface and then find out the
170 /// actual name by this method before proceeding.
171 pub fn name(&self) -> &str {
172 &self.name
173 }
174 /// Receives a packet from the interface.
175 ///
176 /// Blocks until a packet is sent into the virtual interface. At that point, the content of the
177 /// packet is copied into the provided buffer.
178 ///
179 /// Make sure the buffer is large enough. It is MTU of the interface (usually 1500, unless
180 /// reconfigured) + 4 for the header in case that packet info is prepended, MTU + size of ethernet frame (38 bytes,
181 /// unless VLan tags are enabled). If the buffer isn't large enough, the packet gets truncated.
182 ///
183 /// # Result
184 ///
185 /// On successful receive, the number of bytes copied into the buffer is returned.
186 pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
187 (&self.fd).read(buf)
188 }
189 /// Sends a packet into the interface.
190 ///
191 /// Sends a packet through the interface. The buffer must be valid representation of a packet
192 /// (with appropriate headers).
193 ///
194 /// It is up to the caller to provide only packets that fit MTU.
195 ///
196 /// # Result
197 ///
198 /// On successful send, the number of bytes sent in the packet is returned. Under normal
199 /// circumstances, this should be the size of the packet passed.
200 ///
201 /// # Notes
202 ///
203 /// The TUN/TAP is a network adapter. Therefore, many errors are handled simply by dropping
204 /// packets. If you pass an invalid packet, it'll likely suceed in sending it, but will be
205 /// dropped somewhere in kernel due to failed validation. If you send packets too fast, they
206 /// are likely to get dropped too. If you send a packet for address that is not assigned to any
207 /// interface and not routed anywhere… you get the idea.
208 pub fn send(&self, buf: &[u8]) -> Result<usize> {
209 (&self.fd).write(buf)
210 }
211}
212
213impl AsRawFd for Iface {
214 fn as_raw_fd(&self) -> RawFd {
215 self.fd.as_raw_fd()
216 }
217}
218
219impl IntoRawFd for Iface {
220 fn into_raw_fd(self) -> RawFd {
221 self.fd.into_raw_fd()
222 }
223}