• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::fs::File;
6 use std::io::Read;
7 use std::io::Result as IoResult;
8 use std::io::Write;
9 use std::mem;
10 use std::net;
11 use std::os::raw::*;
12 use std::os::unix::io::AsRawFd;
13 use std::os::unix::io::FromRawFd;
14 use std::os::unix::io::RawFd;
15 
16 use base::add_fd_flags;
17 use base::error;
18 use base::ioctl_with_mut_ref;
19 use base::ioctl_with_ref;
20 use base::ioctl_with_val;
21 use base::volatile_impl;
22 use base::warn;
23 use base::AsRawDescriptor;
24 use base::Error as SysError;
25 use base::FileReadWriteVolatile;
26 use base::FromRawDescriptor;
27 use base::IoctlNr;
28 use base::RawDescriptor;
29 use base::ReadNotifier;
30 use cros_async::IntoAsync;
31 
32 use crate::sys::linux::TapTLinux;
33 use crate::Error;
34 use crate::MacAddress;
35 use crate::Result;
36 use crate::TapT;
37 use crate::TapTCommon;
38 
39 /// Handle for a network tap interface.
40 ///
41 /// For now, this simply wraps the file descriptor for the tap device so methods
42 /// can run ioctls on the interface. The tap interface descriptor will be closed when
43 /// Tap goes out of scope, and the kernel will clean up the interface
44 /// automatically.
45 #[derive(Debug)]
46 pub struct Tap {
47     tap_file: File,
48     if_name: [c_char; 16usize],
49     if_flags: ::std::os::raw::c_short,
50 }
51 
52 impl Tap {
53     /// # Safety
54     /// 1. descriptor's ownership must be released by the caller. It is now owned by the returned
55     ///    value (`Tap`), or is closed (if an error is returned).
from_raw_descriptor(descriptor: RawDescriptor) -> Result<Tap>56     pub unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Tap> {
57         let tap_file = File::from_raw_descriptor(descriptor);
58 
59         // Ensure that the file is opened non-blocking, otherwise
60         // ipvtaps with shell-provided FDs are very slow.
61         add_fd_flags(tap_file.as_raw_descriptor(), libc::O_NONBLOCK).map_err(Error::IoctlError)?;
62 
63         // Get the interface name since we will need it for some ioctls.
64         let mut ifreq: net_sys::ifreq = Default::default();
65         let ret = ioctl_with_mut_ref(&tap_file, net_sys::TUNGETIFF(), &mut ifreq);
66 
67         if ret < 0 {
68             return Err(Error::IoctlError(SysError::last()));
69         }
70 
71         Ok(Tap {
72             tap_file,
73             if_name: ifreq.ifr_ifrn.ifrn_name,
74             if_flags: ifreq.ifr_ifru.ifru_flags,
75         })
76     }
77 
create_tap_with_ifreq(ifreq: &mut net_sys::ifreq) -> Result<Tap>78     pub fn create_tap_with_ifreq(ifreq: &mut net_sys::ifreq) -> Result<Tap> {
79         // SAFETY:
80         // Open calls are safe because we give a constant nul-terminated
81         // string and verify the result.
82         let rd = unsafe {
83             libc::open64(
84                 b"/dev/net/tun\0".as_ptr() as *const c_char,
85                 libc::O_RDWR | libc::O_NONBLOCK | libc::O_CLOEXEC,
86             )
87         };
88         if rd < 0 {
89             return Err(Error::OpenTun(SysError::last()));
90         }
91 
92         // SAFETY:
93         // We just checked that the fd is valid.
94         let tuntap = unsafe { File::from_raw_descriptor(rd) };
95         // SAFETY:
96         // ioctl is safe since we call it with a valid tap fd and check the return
97         // value.
98         let ret = unsafe { ioctl_with_mut_ref(&tuntap, net_sys::TUNSETIFF(), ifreq) };
99 
100         if ret < 0 {
101             return Err(Error::CreateTap(SysError::last()));
102         }
103 
104         Ok(Tap {
105             tap_file: tuntap,
106             // SAFETY:
107             // Safe since only the name is accessed, and it's copied out.
108             if_name: unsafe { ifreq.ifr_ifrn.ifrn_name },
109             // SAFETY:
110             // Safe since only the name is accessed, and it's copied out.
111             if_flags: unsafe { ifreq.ifr_ifru.ifru_flags },
112         })
113     }
114 
get_ifreq(&self) -> net_sys::ifreq115     fn get_ifreq(&self) -> net_sys::ifreq {
116         let mut ifreq: net_sys::ifreq = Default::default();
117 
118         // SAFETY:
119         // This sets the name of the interface, which is the only entry
120         // in a single-field union.
121         unsafe {
122             let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
123             ifrn_name.clone_from_slice(&self.if_name);
124         }
125 
126         // This sets the flags with which the interface was created, which is the only entry we set
127         // on the second union.
128         ifreq.ifr_ifru.ifru_flags = self.if_flags;
129 
130         ifreq
131     }
132 
try_clone(&self) -> Result<Tap>133     pub fn try_clone(&self) -> Result<Tap> {
134         self.tap_file
135             .try_clone()
136             .map(|tap_file| Tap {
137                 tap_file,
138                 if_name: self.if_name,
139                 if_flags: self.if_flags,
140             })
141             .map_err(SysError::from)
142             .map_err(Error::CloneTap)
143     }
144 }
145 
146 impl TapTCommon for Tap {
147     /// Create a new tap interface.
148     ///
149     /// Set the `vnet_hdr` flag to true to allow offloading on this tap,
150     /// which will add an extra 12 byte virtio net header to incoming frames. Offloading cannot
151     /// be used if `vnet_hdr` is false.
152     /// Set 'multi_vq' to true, if tap have multi virt queue pairs
new(vnet_hdr: bool, multi_vq: bool) -> Result<Self>153     fn new(vnet_hdr: bool, multi_vq: bool) -> Result<Self> {
154         const TUNTAP_DEV_FORMAT: &[u8] = b"vmtap%d";
155         Self::new_with_name(TUNTAP_DEV_FORMAT, vnet_hdr, multi_vq)
156     }
157 
new_with_name(name: &[u8], vnet_hdr: bool, multi_vq: bool) -> Result<Tap>158     fn new_with_name(name: &[u8], vnet_hdr: bool, multi_vq: bool) -> Result<Tap> {
159         let mut ifreq: net_sys::ifreq = Default::default();
160         // SAFETY:
161         // This is pretty messy because of the unions used by ifreq. Since we
162         // don't call as_mut on the same union field more than once, this block
163         // is safe.
164         unsafe {
165             let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
166             for (dst, src) in ifrn_name
167                 .iter_mut()
168                 // Add a zero terminator to the source string.
169                 .zip(name.iter().chain(std::iter::once(&0)))
170             {
171                 *dst = *src as c_char;
172             }
173             ifreq.ifr_ifru.ifru_flags =
174                 (libc::IFF_TAP | libc::IFF_NO_PI | if vnet_hdr { libc::IFF_VNET_HDR } else { 0 })
175                     as c_short;
176             if multi_vq {
177                 ifreq.ifr_ifru.ifru_flags |= libc::IFF_MULTI_QUEUE as c_short;
178             }
179         }
180 
181         Tap::create_tap_with_ifreq(&mut ifreq)
182     }
183 
into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Tap>>184     fn into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Tap>> {
185         let mut taps: Vec<Tap> = Vec::new();
186 
187         if vq_pairs <= 1 {
188             taps.push(self);
189             return Ok(taps);
190         }
191 
192         // Add other socket into the origin tap interface
193         for _ in 0..vq_pairs - 1 {
194             let mut ifreq = self.get_ifreq();
195             let tap = Tap::create_tap_with_ifreq(&mut ifreq)?;
196 
197             tap.enable()?;
198 
199             taps.push(tap);
200         }
201 
202         taps.insert(0, self);
203         Ok(taps)
204     }
205 
ip_addr(&self) -> Result<net::Ipv4Addr>206     fn ip_addr(&self) -> Result<net::Ipv4Addr> {
207         let sock = create_socket()?;
208         let mut ifreq = self.get_ifreq();
209 
210         // SAFETY:
211         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
212         let ret = unsafe {
213             ioctl_with_mut_ref(&sock, net_sys::sockios::SIOCGIFADDR as IoctlNr, &mut ifreq)
214         };
215 
216         if ret < 0 {
217             return Err(Error::IoctlError(SysError::last()));
218         }
219 
220         // SAFETY:
221         // We only access one field of the ifru union, hence this is safe.
222         let addr = unsafe { ifreq.ifr_ifru.ifru_addr };
223 
224         Ok(read_ipv4_addr(&addr))
225     }
226 
set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>227     fn set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()> {
228         let sock = create_socket()?;
229         let addr = create_sockaddr(ip_addr);
230 
231         let mut ifreq = self.get_ifreq();
232         ifreq.ifr_ifru.ifru_addr = addr;
233 
234         let ret =
235         // SAFETY:
236         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
237             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFADDR as IoctlNr, &ifreq) };
238         if ret < 0 {
239             return Err(Error::IoctlError(SysError::last()));
240         }
241 
242         Ok(())
243     }
244 
netmask(&self) -> Result<net::Ipv4Addr>245     fn netmask(&self) -> Result<net::Ipv4Addr> {
246         let sock = create_socket()?;
247         let mut ifreq = self.get_ifreq();
248 
249         // SAFETY:
250         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
251         let ret = unsafe {
252             ioctl_with_mut_ref(
253                 &sock,
254                 net_sys::sockios::SIOCGIFNETMASK as IoctlNr,
255                 &mut ifreq,
256             )
257         };
258         if ret < 0 {
259             return Err(Error::IoctlError(SysError::last()));
260         }
261 
262         // SAFETY:
263         // We only access one field of the ifru union, hence this is safe.
264         let addr = unsafe { ifreq.ifr_ifru.ifru_netmask };
265 
266         Ok(read_ipv4_addr(&addr))
267     }
268 
set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>269     fn set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()> {
270         let sock = create_socket()?;
271         let addr = create_sockaddr(netmask);
272 
273         let mut ifreq = self.get_ifreq();
274         ifreq.ifr_ifru.ifru_netmask = addr;
275 
276         let ret =
277         // SAFETY:
278         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
279             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFNETMASK as IoctlNr, &ifreq) };
280         if ret < 0 {
281             return Err(Error::IoctlError(SysError::last()));
282         }
283 
284         Ok(())
285     }
286 
mtu(&self) -> Result<u16>287     fn mtu(&self) -> Result<u16> {
288         let sock = create_socket()?;
289         let mut ifreq = self.get_ifreq();
290 
291         // SAFETY:
292         // ioctl is safe. Called with a valid sock fd, and we check the return.
293         let ret = unsafe {
294             ioctl_with_mut_ref(&sock, net_sys::sockios::SIOCGIFMTU as IoctlNr, &mut ifreq)
295         };
296         if ret < 0 {
297             return Err(Error::IoctlError(SysError::last()));
298         }
299 
300         // SAFETY:
301         // We only access one field of the ifru union, hence this is safe.
302         let mtu = unsafe { ifreq.ifr_ifru.ifru_mtu } as u16;
303         Ok(mtu)
304     }
305 
set_mtu(&self, mtu: u16) -> Result<()>306     fn set_mtu(&self, mtu: u16) -> Result<()> {
307         let sock = create_socket()?;
308 
309         let mut ifreq = self.get_ifreq();
310         ifreq.ifr_ifru.ifru_mtu = i32::from(mtu);
311 
312         // SAFETY:
313         // ioctl is safe. Called with a valid sock fd, and we check the return.
314         let ret = unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFMTU as IoctlNr, &ifreq) };
315         if ret < 0 {
316             return Err(Error::IoctlError(SysError::last()));
317         }
318 
319         Ok(())
320     }
321 
mac_address(&self) -> Result<MacAddress>322     fn mac_address(&self) -> Result<MacAddress> {
323         let sock = create_socket()?;
324         let mut ifreq = self.get_ifreq();
325 
326         // SAFETY:
327         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
328         let ret = unsafe {
329             ioctl_with_mut_ref(
330                 &sock,
331                 net_sys::sockios::SIOCGIFHWADDR as IoctlNr,
332                 &mut ifreq,
333             )
334         };
335         if ret < 0 {
336             return Err(Error::IoctlError(SysError::last()));
337         }
338 
339         // SAFETY:
340         // We only access one field of the ifru union, hence this is safe.
341         let sa: libc::sockaddr = unsafe { ifreq.ifr_ifru.ifru_hwaddr };
342 
343         if sa.sa_family != libc::ARPHRD_ETHER {
344             return Err(crate::Error::IoctlError(base::Error::new(libc::EINVAL)));
345         }
346 
347         let mut mac = MacAddress::default();
348 
349         #[allow(clippy::unnecessary_cast)] // c_char is u8 on some platforms and i8 on others
350         for (mac_addr, sa_data) in mac.addr.iter_mut().zip(sa.sa_data.iter()) {
351             *mac_addr = *sa_data as u8;
352         }
353 
354         Ok(mac)
355     }
356 
set_mac_address(&self, mac_addr: MacAddress) -> Result<()>357     fn set_mac_address(&self, mac_addr: MacAddress) -> Result<()> {
358         let mut sa = libc::sockaddr {
359             sa_family: libc::ARPHRD_ETHER,
360             sa_data: Default::default(),
361         };
362 
363         #[allow(clippy::unnecessary_cast)] // c_char is u8 on some platforms and i8 on others
364         for (sa_data, mac) in sa
365             .sa_data
366             .iter_mut()
367             .zip(mac_addr.octets().iter().chain(std::iter::repeat(&0)))
368         {
369             *sa_data = *mac as c_char;
370         }
371 
372         let sock = create_socket()?;
373 
374         let mut ifreq = self.get_ifreq();
375         ifreq.ifr_ifru.ifru_hwaddr = sa;
376 
377         let ret =
378         // SAFETY:
379         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
380             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFHWADDR as IoctlNr, &ifreq) };
381         if ret < 0 {
382             return Err(Error::IoctlError(SysError::last()));
383         }
384 
385         Ok(())
386     }
387 
set_offload(&self, flags: c_uint) -> Result<()>388     fn set_offload(&self, flags: c_uint) -> Result<()> {
389         let ret =
390         // SAFETY:
391         // ioctl is safe. Called with a valid tap descriptor, and we check the return.
392             unsafe { ioctl_with_val(&self.tap_file, net_sys::TUNSETOFFLOAD(), flags as c_ulong) };
393         if ret < 0 {
394             return Err(Error::IoctlError(SysError::last()));
395         }
396 
397         Ok(())
398     }
399 
enable(&self) -> Result<()>400     fn enable(&self) -> Result<()> {
401         let sock = create_socket()?;
402 
403         let mut ifreq = self.get_ifreq();
404         ifreq.ifr_ifru.ifru_flags =
405             (net_sys::net_device_flags::IFF_UP | net_sys::net_device_flags::IFF_RUNNING).0 as i16;
406 
407         let ret =
408         // SAFETY:
409         // ioctl is safe. Called with a valid sock descriptor, and we check the return.
410             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFFLAGS as IoctlNr, &ifreq) };
411         if ret < 0 {
412             return Err(Error::IoctlError(SysError::last()));
413         }
414 
415         Ok(())
416     }
417 
try_clone(&self) -> Result<Self>418     fn try_clone(&self) -> Result<Self> {
419         self.try_clone()
420     }
421 
422     // SAFETY:
423     // Safe if caller provides a valid descriptor.
from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self>424     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self> {
425         Tap::from_raw_descriptor(descriptor)
426     }
427 }
428 
429 impl TapTLinux for Tap {
set_vnet_hdr_size(&self, size: usize) -> Result<()>430     fn set_vnet_hdr_size(&self, size: usize) -> Result<()> {
431         let size = size as c_int;
432         // SAFETY:
433         // ioctl is safe. Called with a valid tap descriptor, and we check the return.
434         let ret = unsafe { ioctl_with_ref(&self.tap_file, net_sys::TUNSETVNETHDRSZ(), &size) };
435         if ret < 0 {
436             return Err(Error::IoctlError(SysError::last()));
437         }
438 
439         Ok(())
440     }
441 
if_flags(&self) -> u32442     fn if_flags(&self) -> u32 {
443         self.if_flags as u32
444     }
445 }
446 
447 impl Read for Tap {
read(&mut self, buf: &mut [u8]) -> IoResult<usize>448     fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
449         self.tap_file.read(buf)
450     }
451 }
452 
453 impl Write for Tap {
write(&mut self, buf: &[u8]) -> IoResult<usize>454     fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
455         self.tap_file.write(buf)
456     }
457 
flush(&mut self) -> IoResult<()>458     fn flush(&mut self) -> IoResult<()> {
459         Ok(())
460     }
461 }
462 
463 impl AsRawFd for Tap {
as_raw_fd(&self) -> RawFd464     fn as_raw_fd(&self) -> RawFd {
465         self.tap_file.as_raw_descriptor()
466     }
467 }
468 
469 impl AsRawDescriptor for Tap {
as_raw_descriptor(&self) -> RawDescriptor470     fn as_raw_descriptor(&self) -> RawDescriptor {
471         self.tap_file.as_raw_descriptor()
472     }
473 }
474 
475 impl ReadNotifier for Tap {
get_read_notifier(&self) -> &dyn AsRawDescriptor476     fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
477         self
478     }
479 }
480 
create_socket() -> Result<net::UdpSocket>481 fn create_socket() -> Result<net::UdpSocket> {
482     // SAFETY:
483     // This is safe since we check the return value.
484     let sock = unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) };
485     if sock >= 0 {
486         // SAFETY:
487         // This is safe; nothing else will use or hold onto the raw sock descriptor.
488         return Ok(unsafe { net::UdpSocket::from_raw_fd(sock) });
489     }
490 
491     warn!("INET not supported on this machine. Trying to open an INET6 socket.");
492 
493     // SAFETY:
494     // Open an AF_INET6 socket
495     let sock6 = unsafe { libc::socket(libc::AF_INET6, libc::SOCK_DGRAM, 0) };
496     if sock6 >= 0 {
497         // SAFETY:
498         // This is safe; nothing else will use or hold onto the raw sock descriptor.
499         return Ok(unsafe { net::UdpSocket::from_raw_fd(sock6) });
500     }
501 
502     error!("Neither INET nor INET6 supported on this machine");
503 
504     Err(Error::CreateSocket(SysError::last()))
505 }
506 
507 /// Create a sockaddr_in from an IPv4 address, and expose it as
508 /// an opaque sockaddr suitable for usage by socket ioctls.
create_sockaddr(ip_addr: net::Ipv4Addr) -> libc::sockaddr509 fn create_sockaddr(ip_addr: net::Ipv4Addr) -> libc::sockaddr {
510     // IPv4 addresses big-endian (network order), but Ipv4Addr will give us
511     // a view of those bytes directly so we can avoid any endian trickiness.
512     let addr_in = libc::sockaddr_in {
513         sin_family: libc::AF_INET as u16,
514         sin_port: 0,
515         // SAFETY: trivially safe
516         sin_addr: unsafe { mem::transmute(ip_addr.octets()) },
517         sin_zero: [0; 8usize],
518     };
519 
520     // SAFETY: trivially safe
521     unsafe { mem::transmute(addr_in) }
522 }
523 
524 /// Extract the IPv4 address from a sockaddr. Assumes the sockaddr is a sockaddr_in.
read_ipv4_addr(addr: &libc::sockaddr) -> net::Ipv4Addr525 fn read_ipv4_addr(addr: &libc::sockaddr) -> net::Ipv4Addr {
526     debug_assert_eq!(addr.sa_family as i32, libc::AF_INET);
527     // SAFETY:
528     // This is safe because sockaddr and sockaddr_in are the same size, and we've checked that
529     // this address is AF_INET.
530     let in_addr: libc::sockaddr_in = unsafe { mem::transmute(*addr) };
531     net::Ipv4Addr::from(in_addr.sin_addr.s_addr)
532 }
533 
534 impl TapT for Tap {}
535 impl IntoAsync for Tap {}
536 volatile_impl!(Tap);
537 
538 pub mod fakes {
539     use std::fs::remove_file;
540     use std::fs::OpenOptions;
541 
542     use super::*;
543 
544     const TMP_FILE: &str = "/tmp/crosvm_tap_test_file";
545 
546     pub struct FakeTap {
547         tap_file: File,
548     }
549 
550     impl TapTCommon for FakeTap {
new(_vnet_hdr: bool, _multi_vq: bool) -> Result<Self>551         fn new(_vnet_hdr: bool, _multi_vq: bool) -> Result<Self> {
552             // Params don't matter
553             Self::new_with_name(b"", false, false)
554         }
555 
new_with_name(_: &[u8], _: bool, _: bool) -> Result<FakeTap>556         fn new_with_name(_: &[u8], _: bool, _: bool) -> Result<FakeTap> {
557             Ok(FakeTap {
558                 tap_file: OpenOptions::new()
559                     .read(true)
560                     .append(true)
561                     .create(true)
562                     .open(TMP_FILE)
563                     .unwrap(),
564             })
565         }
566 
into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>>567         fn into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>> {
568             Ok(Vec::new())
569         }
570 
ip_addr(&self) -> Result<net::Ipv4Addr>571         fn ip_addr(&self) -> Result<net::Ipv4Addr> {
572             Ok(net::Ipv4Addr::new(1, 2, 3, 4))
573         }
574 
set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()>575         fn set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()> {
576             Ok(())
577         }
578 
netmask(&self) -> Result<net::Ipv4Addr>579         fn netmask(&self) -> Result<net::Ipv4Addr> {
580             Ok(net::Ipv4Addr::new(255, 255, 255, 252))
581         }
582 
set_netmask(&self, _: net::Ipv4Addr) -> Result<()>583         fn set_netmask(&self, _: net::Ipv4Addr) -> Result<()> {
584             Ok(())
585         }
586 
mtu(&self) -> Result<u16>587         fn mtu(&self) -> Result<u16> {
588             Ok(1500)
589         }
590 
set_mtu(&self, _: u16) -> Result<()>591         fn set_mtu(&self, _: u16) -> Result<()> {
592             Ok(())
593         }
594 
mac_address(&self) -> Result<MacAddress>595         fn mac_address(&self) -> Result<MacAddress> {
596             Ok("01:02:03:04:05:06".parse().unwrap())
597         }
598 
set_mac_address(&self, _: MacAddress) -> Result<()>599         fn set_mac_address(&self, _: MacAddress) -> Result<()> {
600             Ok(())
601         }
602 
set_offload(&self, _: c_uint) -> Result<()>603         fn set_offload(&self, _: c_uint) -> Result<()> {
604             Ok(())
605         }
606 
enable(&self) -> Result<()>607         fn enable(&self) -> Result<()> {
608             Ok(())
609         }
610 
611         // Return self so it can compile
try_clone(&self) -> Result<Self>612         fn try_clone(&self) -> Result<Self> {
613             Ok(FakeTap {
614                 tap_file: self.tap_file.try_clone().unwrap(),
615             })
616         }
617 
from_raw_descriptor(_descriptor: RawDescriptor) -> Result<Self>618         unsafe fn from_raw_descriptor(_descriptor: RawDescriptor) -> Result<Self> {
619             unimplemented!()
620         }
621     }
622 
623     impl TapTLinux for FakeTap {
set_vnet_hdr_size(&self, _: usize) -> Result<()>624         fn set_vnet_hdr_size(&self, _: usize) -> Result<()> {
625             Ok(())
626         }
627 
if_flags(&self) -> u32628         fn if_flags(&self) -> u32 {
629             net_sys::IFF_TAP
630         }
631     }
632 
633     impl Drop for FakeTap {
drop(&mut self)634         fn drop(&mut self) {
635             let _ = remove_file(TMP_FILE);
636         }
637     }
638 
639     impl Read for FakeTap {
read(&mut self, _: &mut [u8]) -> IoResult<usize>640         fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
641             Ok(0)
642         }
643     }
644 
645     impl Write for FakeTap {
write(&mut self, _: &[u8]) -> IoResult<usize>646         fn write(&mut self, _: &[u8]) -> IoResult<usize> {
647             Ok(0)
648         }
649 
flush(&mut self) -> IoResult<()>650         fn flush(&mut self) -> IoResult<()> {
651             Ok(())
652         }
653     }
654 
655     impl AsRawFd for FakeTap {
as_raw_fd(&self) -> RawFd656         fn as_raw_fd(&self) -> RawFd {
657             self.tap_file.as_raw_descriptor()
658         }
659     }
660 
661     impl AsRawDescriptor for FakeTap {
as_raw_descriptor(&self) -> RawDescriptor662         fn as_raw_descriptor(&self) -> RawDescriptor {
663             self.tap_file.as_raw_descriptor()
664         }
665     }
666     impl TapT for FakeTap {}
667     volatile_impl!(FakeTap);
668 }
669