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