tun_easytier/platform/linux/
device.rs1use 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
38pub 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 pub fn new(config: &Configuration) -> Result<Self> {
60 let mut device = unsafe {
61 if config.raw_fd.is_some() {
62 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 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 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 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 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 pub fn split(self) -> (posix::Reader, posix::Writer) {
182 (self.tun.reader, self.tun.writer)
183 }
184
185 pub fn set_nonblock(&self) -> io::Result<()> {
187 self.tun.set_nonblock()
188 }
189
190 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
192 self.tun.recv(buf)
193 }
194
195 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}