xref: /aosp_15_r20/external/crosvm/net_util/src/sys/linux/tap.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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 
sockaddr_from_sockaddr_in(addr_in: libc::sockaddr_in) -> libc::sockaddr507 fn sockaddr_from_sockaddr_in(addr_in: libc::sockaddr_in) -> libc::sockaddr {
508     assert_eq!(
509         mem::size_of::<libc::sockaddr_in>(),
510         mem::size_of::<libc::sockaddr>()
511     );
512 
513     // SAFETY: trivially safe
514     unsafe { mem::transmute::<libc::sockaddr_in, libc::sockaddr>(addr_in) }
515 }
516 
sockaddr_in_from_sockaddr(addr: libc::sockaddr) -> Option<libc::sockaddr_in>517 fn sockaddr_in_from_sockaddr(addr: libc::sockaddr) -> Option<libc::sockaddr_in> {
518     if addr.sa_family as i32 != libc::AF_INET {
519         return None;
520     }
521 
522     assert_eq!(
523         mem::size_of::<libc::sockaddr_in>(),
524         mem::size_of::<libc::sockaddr>()
525     );
526 
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     Some(unsafe { mem::transmute::<libc::sockaddr, libc::sockaddr_in>(addr) })
531 }
532 
533 /// Create a sockaddr_in from an IPv4 address, and expose it as
534 /// an opaque sockaddr suitable for usage by socket ioctls.
create_sockaddr(ip_addr: net::Ipv4Addr) -> libc::sockaddr535 fn create_sockaddr(ip_addr: net::Ipv4Addr) -> libc::sockaddr {
536     let addr_in = libc::sockaddr_in {
537         sin_family: libc::AF_INET as u16,
538         sin_port: 0,
539         sin_addr: libc::in_addr {
540             // `Ipv4Addr::octets()` returns the address in network byte order, so use
541             // `from_be_bytes()` to convert it into the native endianness, then `to_be()` to convert
542             // it back into big-endian (network) byte order as required by `sockaddr_in`. This is
543             // effectively a no-op, and we could use `u32::from_ne_bytes()` instead, but it is
544             // easier to understand when written this way.
545             s_addr: u32::from_be_bytes(ip_addr.octets()).to_be(),
546         },
547         sin_zero: [0; 8usize],
548     };
549 
550     sockaddr_from_sockaddr_in(addr_in)
551 }
552 
553 /// Extract the IPv4 address from a sockaddr. Assumes the sockaddr is a sockaddr_in.
read_ipv4_addr(addr: &libc::sockaddr) -> net::Ipv4Addr554 fn read_ipv4_addr(addr: &libc::sockaddr) -> net::Ipv4Addr {
555     let in_addr = sockaddr_in_from_sockaddr(*addr).unwrap();
556     net::Ipv4Addr::from(in_addr.sin_addr.s_addr)
557 }
558 
559 impl TapT for Tap {}
560 impl IntoAsync for Tap {}
561 volatile_impl!(Tap);
562 
563 pub mod fakes {
564     use std::fs::remove_file;
565     use std::fs::OpenOptions;
566 
567     use super::*;
568 
569     const TMP_FILE: &str = "/tmp/crosvm_tap_test_file";
570 
571     pub struct FakeTap {
572         tap_file: File,
573     }
574 
575     impl TapTCommon for FakeTap {
new(_vnet_hdr: bool, _multi_vq: bool) -> Result<Self>576         fn new(_vnet_hdr: bool, _multi_vq: bool) -> Result<Self> {
577             // Params don't matter
578             Self::new_with_name(b"", false, false)
579         }
580 
new_with_name(_: &[u8], _: bool, _: bool) -> Result<FakeTap>581         fn new_with_name(_: &[u8], _: bool, _: bool) -> Result<FakeTap> {
582             Ok(FakeTap {
583                 tap_file: OpenOptions::new()
584                     .read(true)
585                     .append(true)
586                     .create(true)
587                     .open(TMP_FILE)
588                     .unwrap(),
589             })
590         }
591 
into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>>592         fn into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>> {
593             Ok(Vec::new())
594         }
595 
ip_addr(&self) -> Result<net::Ipv4Addr>596         fn ip_addr(&self) -> Result<net::Ipv4Addr> {
597             Ok(net::Ipv4Addr::new(1, 2, 3, 4))
598         }
599 
set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()>600         fn set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()> {
601             Ok(())
602         }
603 
netmask(&self) -> Result<net::Ipv4Addr>604         fn netmask(&self) -> Result<net::Ipv4Addr> {
605             Ok(net::Ipv4Addr::new(255, 255, 255, 252))
606         }
607 
set_netmask(&self, _: net::Ipv4Addr) -> Result<()>608         fn set_netmask(&self, _: net::Ipv4Addr) -> Result<()> {
609             Ok(())
610         }
611 
mtu(&self) -> Result<u16>612         fn mtu(&self) -> Result<u16> {
613             Ok(1500)
614         }
615 
set_mtu(&self, _: u16) -> Result<()>616         fn set_mtu(&self, _: u16) -> Result<()> {
617             Ok(())
618         }
619 
mac_address(&self) -> Result<MacAddress>620         fn mac_address(&self) -> Result<MacAddress> {
621             Ok("01:02:03:04:05:06".parse().unwrap())
622         }
623 
set_mac_address(&self, _: MacAddress) -> Result<()>624         fn set_mac_address(&self, _: MacAddress) -> Result<()> {
625             Ok(())
626         }
627 
set_offload(&self, _: c_uint) -> Result<()>628         fn set_offload(&self, _: c_uint) -> Result<()> {
629             Ok(())
630         }
631 
enable(&self) -> Result<()>632         fn enable(&self) -> Result<()> {
633             Ok(())
634         }
635 
636         // Return self so it can compile
try_clone(&self) -> Result<Self>637         fn try_clone(&self) -> Result<Self> {
638             Ok(FakeTap {
639                 tap_file: self.tap_file.try_clone().unwrap(),
640             })
641         }
642 
from_raw_descriptor(_descriptor: RawDescriptor) -> Result<Self>643         unsafe fn from_raw_descriptor(_descriptor: RawDescriptor) -> Result<Self> {
644             unimplemented!()
645         }
646     }
647 
648     impl TapTLinux for FakeTap {
set_vnet_hdr_size(&self, _: usize) -> Result<()>649         fn set_vnet_hdr_size(&self, _: usize) -> Result<()> {
650             Ok(())
651         }
652 
if_flags(&self) -> u32653         fn if_flags(&self) -> u32 {
654             net_sys::IFF_TAP
655         }
656     }
657 
658     impl Drop for FakeTap {
drop(&mut self)659         fn drop(&mut self) {
660             let _ = remove_file(TMP_FILE);
661         }
662     }
663 
664     impl Read for FakeTap {
read(&mut self, _: &mut [u8]) -> IoResult<usize>665         fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
666             Ok(0)
667         }
668     }
669 
670     impl Write for FakeTap {
write(&mut self, _: &[u8]) -> IoResult<usize>671         fn write(&mut self, _: &[u8]) -> IoResult<usize> {
672             Ok(0)
673         }
674 
flush(&mut self) -> IoResult<()>675         fn flush(&mut self) -> IoResult<()> {
676             Ok(())
677         }
678     }
679 
680     impl AsRawFd for FakeTap {
as_raw_fd(&self) -> RawFd681         fn as_raw_fd(&self) -> RawFd {
682             self.tap_file.as_raw_descriptor()
683         }
684     }
685 
686     impl AsRawDescriptor for FakeTap {
as_raw_descriptor(&self) -> RawDescriptor687         fn as_raw_descriptor(&self) -> RawDescriptor {
688             self.tap_file.as_raw_descriptor()
689         }
690     }
691     impl TapT for FakeTap {}
692     volatile_impl!(FakeTap);
693 }
694 
695 #[cfg(test)]
696 pub mod tests {
697     use super::*;
698 
699     #[test]
sockaddr_byte_order()700     fn sockaddr_byte_order() {
701         let sa = create_sockaddr(net::Ipv4Addr::new(1, 2, 3, 4));
702         assert_eq!(sa.sa_family, 2); // AF_INET
703         assert_eq!(
704             sa.sa_data,
705             [
706                 0, 0, // sin_port
707                 1, 2, 3, 4, // sin_addr
708                 0, 0, 0, 0, 0, 0, 0, 0, // sin_zero
709             ]
710         );
711     }
712 }
713