• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
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::fmt::{self, Display};
6 use std::fs::File;
7 use std::io::{Read, Result as IoResult, Write};
8 use std::mem;
9 use std::net;
10 use std::num::ParseIntError;
11 use std::os::raw::*;
12 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
13 use std::str::FromStr;
14 
15 use libc::EPERM;
16 
17 use base::Error as SysError;
18 use base::FileReadWriteVolatile;
19 use base::{
20     ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val, volatile_impl, AsRawDescriptor,
21     FromRawDescriptor, IoctlNr, RawDescriptor,
22 };
23 
24 #[derive(Debug)]
25 pub enum Error {
26     /// Failed to create a socket.
27     CreateSocket(SysError),
28     /// Couldn't open /dev/net/tun.
29     OpenTun(SysError),
30     /// Unable to create tap interface.
31     CreateTap(SysError),
32     /// ioctl failed.
33     IoctlError(SysError),
34 }
35 pub type Result<T> = std::result::Result<T, Error>;
36 
37 impl Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39         use self::Error::*;
40 
41         match self {
42             CreateSocket(e) => write!(f, "failed to create a socket: {}", e),
43             OpenTun(e) => write!(f, "failed to open /dev/net/tun: {}", e),
44             CreateTap(e) => write!(f, "failed to create tap interface: {}", e),
45             IoctlError(e) => write!(f, "ioctl failed: {}", e),
46         }
47     }
48 }
49 
50 impl Error {
sys_error(&self) -> SysError51     pub fn sys_error(&self) -> SysError {
52         match *self {
53             Error::CreateSocket(e) => e,
54             Error::OpenTun(e) => e,
55             Error::CreateTap(e) => e,
56             Error::IoctlError(e) => e,
57         }
58     }
59 }
60 
61 /// Create a sockaddr_in from an IPv4 address, and expose it as
62 /// an opaque sockaddr suitable for usage by socket ioctls.
create_sockaddr(ip_addr: net::Ipv4Addr) -> net_sys::sockaddr63 fn create_sockaddr(ip_addr: net::Ipv4Addr) -> net_sys::sockaddr {
64     // IPv4 addresses big-endian (network order), but Ipv4Addr will give us
65     // a view of those bytes directly so we can avoid any endian trickiness.
66     let addr_in = net_sys::sockaddr_in {
67         sin_family: net_sys::AF_INET as u16,
68         sin_port: 0,
69         sin_addr: unsafe { mem::transmute(ip_addr.octets()) },
70         __pad: [0; 8usize],
71     };
72 
73     unsafe { mem::transmute(addr_in) }
74 }
75 
76 /// Extract the IPv4 address from a sockaddr. Assumes the sockaddr is a sockaddr_in.
read_ipv4_addr(addr: &net_sys::sockaddr) -> net::Ipv4Addr77 fn read_ipv4_addr(addr: &net_sys::sockaddr) -> net::Ipv4Addr {
78     debug_assert_eq!(addr.sa_family as u32, net_sys::AF_INET);
79     // This is safe because sockaddr and sockaddr_in are the same size, and we've checked that
80     // this address is AF_INET.
81     let in_addr: net_sys::sockaddr_in = unsafe { mem::transmute(*addr) };
82     net::Ipv4Addr::from(in_addr.sin_addr.s_addr)
83 }
84 
create_socket() -> Result<net::UdpSocket>85 fn create_socket() -> Result<net::UdpSocket> {
86     // This is safe since we check the return value.
87     let sock = unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) };
88     if sock < 0 {
89         return Err(Error::CreateSocket(SysError::last()));
90     }
91 
92     // This is safe; nothing else will use or hold onto the raw sock fd.
93     Ok(unsafe { net::UdpSocket::from_raw_fd(sock) })
94 }
95 
96 #[derive(Debug)]
97 pub enum MacAddressError {
98     /// Invalid number of octets.
99     InvalidNumOctets(usize),
100     /// Failed to parse octet.
101     ParseOctet(ParseIntError),
102 }
103 
104 impl Display for MacAddressError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result105     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106         use self::MacAddressError::*;
107 
108         match self {
109             InvalidNumOctets(n) => write!(f, "invalid number of octets: {}", n),
110             ParseOctet(e) => write!(f, "failed to parse octet: {}", e),
111         }
112     }
113 }
114 
115 /// An Ethernet mac address. This struct is compatible with the C `struct sockaddr`.
116 #[repr(C)]
117 #[derive(Clone, Copy)]
118 pub struct MacAddress {
119     family: net_sys::sa_family_t,
120     addr: [u8; 6usize],
121     __pad: [u8; 8usize],
122 }
123 
124 impl MacAddress {
octets(&self) -> [u8; 6usize]125     pub fn octets(&self) -> [u8; 6usize] {
126         self.addr
127     }
128 }
129 
130 impl FromStr for MacAddress {
131     type Err = MacAddressError;
132 
from_str(s: &str) -> std::result::Result<Self, Self::Err>133     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
134         let octets: Vec<&str> = s.split(':').collect();
135         if octets.len() != 6usize {
136             return Err(MacAddressError::InvalidNumOctets(octets.len()));
137         }
138 
139         let mut result = MacAddress {
140             family: net_sys::ARPHRD_ETHER,
141             addr: [0; 6usize],
142             __pad: [0; 8usize],
143         };
144 
145         for (i, octet) in octets.iter().enumerate() {
146             result.addr[i] = u8::from_str_radix(octet, 16).map_err(MacAddressError::ParseOctet)?;
147         }
148 
149         Ok(result)
150     }
151 }
152 
153 impl Display for MacAddress {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result154     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155         write!(
156             f,
157             "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
158             self.addr[0], self.addr[1], self.addr[2], self.addr[3], self.addr[4], self.addr[5]
159         )
160     }
161 }
162 
163 /// Handle for a network tap interface.
164 ///
165 /// For now, this simply wraps the file descriptor for the tap device so methods
166 /// can run ioctls on the interface. The tap interface fd will be closed when
167 /// Tap goes out of scope, and the kernel will clean up the interface
168 /// automatically.
169 #[derive(Debug)]
170 pub struct Tap {
171     tap_file: File,
172     if_name: [c_char; 16usize],
173     if_flags: ::std::os::raw::c_short,
174 }
175 
176 impl Tap {
from_raw_descriptor(fd: RawDescriptor) -> Result<Tap>177     pub unsafe fn from_raw_descriptor(fd: RawDescriptor) -> Result<Tap> {
178         let tap_file = File::from_raw_descriptor(fd);
179 
180         // Get the interface name since we will need it for some ioctls.
181         let mut ifreq: net_sys::ifreq = Default::default();
182         let ret = ioctl_with_mut_ref(&tap_file, net_sys::TUNGETIFF(), &mut ifreq);
183 
184         if ret < 0 {
185             return Err(Error::IoctlError(SysError::last()));
186         }
187 
188         Ok(Tap {
189             tap_file,
190             if_name: ifreq.ifr_ifrn.ifrn_name,
191             if_flags: ifreq.ifr_ifru.ifru_flags,
192         })
193     }
194 
create_tap_with_ifreq(ifreq: &mut net_sys::ifreq) -> Result<Tap>195     fn create_tap_with_ifreq(ifreq: &mut net_sys::ifreq) -> Result<Tap> {
196         // Open calls are safe because we give a constant nul-terminated
197         // string and verify the result.
198         let fd = unsafe {
199             libc::open(
200                 b"/dev/net/tun\0".as_ptr() as *const c_char,
201                 libc::O_RDWR | libc::O_NONBLOCK | libc::O_CLOEXEC,
202             )
203         };
204         if fd < 0 {
205             return Err(Error::OpenTun(SysError::last()));
206         }
207 
208         // We just checked that the fd is valid.
209         let tuntap = unsafe { File::from_raw_descriptor(fd) };
210         // ioctl is safe since we call it with a valid tap fd and check the return
211         // value.
212         let ret = unsafe { ioctl_with_mut_ref(&tuntap, net_sys::TUNSETIFF(), ifreq) };
213 
214         if ret < 0 {
215             let error = SysError::last();
216 
217             // In a non-root, test environment, we won't have permission to call this; allow
218             if !(cfg!(test) && error.errno() == EPERM) {
219                 return Err(Error::CreateTap(error));
220             }
221         }
222 
223         // Safe since only the name is accessed, and it's copied out.
224         Ok(Tap {
225             tap_file: tuntap,
226             if_name: unsafe { ifreq.ifr_ifrn.ifrn_name },
227             if_flags: unsafe { ifreq.ifr_ifru.ifru_flags },
228         })
229     }
230 }
231 
232 pub trait TapT: FileReadWriteVolatile + Read + Write + AsRawDescriptor + Send + Sized {
233     /// Create a new tap interface. Set the `vnet_hdr` flag to true to allow offloading on this tap,
234     /// which will add an extra 12 byte virtio net header to incoming frames. Offloading cannot
235     /// be used if `vnet_hdr` is false.
236     /// set 'multi_vq' to ture, if tap have multi virt queue pairs
new(vnet_hdr: bool, multi_vq: bool) -> Result<Self>237     fn new(vnet_hdr: bool, multi_vq: bool) -> Result<Self>;
238 
239     /// Change the origin tap into multiqueue taps, this means create other taps based on the
240     /// origin tap.
into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Self>>241     fn into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Self>>;
242 
243     /// Get the host-side IP address for the tap interface.
ip_addr(&self) -> Result<net::Ipv4Addr>244     fn ip_addr(&self) -> Result<net::Ipv4Addr>;
245 
246     /// Set the host-side IP address for the tap interface.
set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>247     fn set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>;
248 
249     /// Get the netmask for the tap interface's subnet.
netmask(&self) -> Result<net::Ipv4Addr>250     fn netmask(&self) -> Result<net::Ipv4Addr>;
251 
252     /// Set the netmask for the subnet that the tap interface will exist on.
set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>253     fn set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>;
254 
255     /// Get the mac address for the tap interface.
mac_address(&self) -> Result<MacAddress>256     fn mac_address(&self) -> Result<MacAddress>;
257 
258     /// Set the mac address for the tap interface.
set_mac_address(&self, mac_addr: MacAddress) -> Result<()>259     fn set_mac_address(&self, mac_addr: MacAddress) -> Result<()>;
260 
261     /// Set the offload flags for the tap interface.
set_offload(&self, flags: c_uint) -> Result<()>262     fn set_offload(&self, flags: c_uint) -> Result<()>;
263 
264     /// Enable the tap interface.
enable(&self) -> Result<()>265     fn enable(&self) -> Result<()>;
266 
267     /// Set the size of the vnet hdr.
set_vnet_hdr_size(&self, size: c_int) -> Result<()>268     fn set_vnet_hdr_size(&self, size: c_int) -> Result<()>;
269 
get_ifreq(&self) -> net_sys::ifreq270     fn get_ifreq(&self) -> net_sys::ifreq;
271 
272     /// Get the interface flags
if_flags(&self) -> u32273     fn if_flags(&self) -> u32;
274 }
275 
276 impl TapT for Tap {
new(vnet_hdr: bool, multi_vq: bool) -> Result<Tap>277     fn new(vnet_hdr: bool, multi_vq: bool) -> Result<Tap> {
278         const TUNTAP_DEV_FORMAT: &[u8; 8usize] = b"vmtap%d\0";
279 
280         // This is pretty messy because of the unions used by ifreq. Since we
281         // don't call as_mut on the same union field more than once, this block
282         // is safe.
283         let mut ifreq: net_sys::ifreq = Default::default();
284         unsafe {
285             let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
286             let name_slice = &mut ifrn_name[..TUNTAP_DEV_FORMAT.len()];
287             for (dst, src) in name_slice.iter_mut().zip(TUNTAP_DEV_FORMAT.iter()) {
288                 *dst = *src as c_char;
289             }
290             ifreq.ifr_ifru.ifru_flags = (net_sys::IFF_TAP
291                 | net_sys::IFF_NO_PI
292                 | if vnet_hdr { net_sys::IFF_VNET_HDR } else { 0 })
293                 as c_short;
294             if multi_vq {
295                 ifreq.ifr_ifru.ifru_flags |= net_sys::IFF_MULTI_QUEUE as c_short;
296             }
297         }
298 
299         Tap::create_tap_with_ifreq(&mut ifreq)
300     }
301 
into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Tap>>302     fn into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Tap>> {
303         let mut taps: Vec<Tap> = Vec::new();
304 
305         if vq_pairs <= 1 {
306             taps.push(self);
307             return Ok(taps);
308         }
309 
310         // Add other socket into the origin tap interface
311         for _ in 0..vq_pairs - 1 {
312             let mut ifreq = self.get_ifreq();
313             let tap = Tap::create_tap_with_ifreq(&mut ifreq)?;
314 
315             tap.enable()?;
316 
317             taps.push(tap);
318         }
319 
320         taps.insert(0, self);
321         Ok(taps)
322     }
323 
ip_addr(&self) -> Result<net::Ipv4Addr>324     fn ip_addr(&self) -> Result<net::Ipv4Addr> {
325         let sock = create_socket()?;
326         let mut ifreq = self.get_ifreq();
327 
328         // ioctl is safe. Called with a valid sock fd, and we check the return.
329         let ret = unsafe {
330             ioctl_with_mut_ref(&sock, net_sys::sockios::SIOCGIFADDR as IoctlNr, &mut ifreq)
331         };
332         if ret < 0 {
333             return Err(Error::IoctlError(SysError::last()));
334         }
335 
336         // We only access one field of the ifru union, hence this is safe.
337         let addr = unsafe { ifreq.ifr_ifru.ifru_addr };
338 
339         Ok(read_ipv4_addr(&addr))
340     }
341 
set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>342     fn set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()> {
343         let sock = create_socket()?;
344         let addr = create_sockaddr(ip_addr);
345 
346         let mut ifreq = self.get_ifreq();
347         ifreq.ifr_ifru.ifru_addr = addr;
348 
349         // ioctl is safe. Called with a valid sock fd, and we check the return.
350         let ret =
351             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFADDR as IoctlNr, &ifreq) };
352         if ret < 0 {
353             return Err(Error::IoctlError(SysError::last()));
354         }
355 
356         Ok(())
357     }
358 
netmask(&self) -> Result<net::Ipv4Addr>359     fn netmask(&self) -> Result<net::Ipv4Addr> {
360         let sock = create_socket()?;
361         let mut ifreq = self.get_ifreq();
362 
363         // ioctl is safe. Called with a valid sock fd, and we check the return.
364         let ret = unsafe {
365             ioctl_with_mut_ref(
366                 &sock,
367                 net_sys::sockios::SIOCGIFNETMASK as IoctlNr,
368                 &mut ifreq,
369             )
370         };
371         if ret < 0 {
372             return Err(Error::IoctlError(SysError::last()));
373         }
374 
375         // We only access one field of the ifru union, hence this is safe.
376         let addr = unsafe { ifreq.ifr_ifru.ifru_netmask };
377 
378         Ok(read_ipv4_addr(&addr))
379     }
380 
set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>381     fn set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()> {
382         let sock = create_socket()?;
383         let addr = create_sockaddr(netmask);
384 
385         let mut ifreq = self.get_ifreq();
386         ifreq.ifr_ifru.ifru_netmask = addr;
387 
388         // ioctl is safe. Called with a valid sock fd, and we check the return.
389         let ret =
390             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFNETMASK as IoctlNr, &ifreq) };
391         if ret < 0 {
392             return Err(Error::IoctlError(SysError::last()));
393         }
394 
395         Ok(())
396     }
397 
mac_address(&self) -> Result<MacAddress>398     fn mac_address(&self) -> Result<MacAddress> {
399         let sock = create_socket()?;
400         let mut ifreq = self.get_ifreq();
401 
402         // ioctl is safe. Called with a valid sock fd, and we check the return.
403         let ret = unsafe {
404             ioctl_with_mut_ref(
405                 &sock,
406                 net_sys::sockios::SIOCGIFHWADDR as IoctlNr,
407                 &mut ifreq,
408             )
409         };
410         if ret < 0 {
411             return Err(Error::IoctlError(SysError::last()));
412         }
413 
414         // We only access one field of the ifru union, hence this is safe.
415         // This is safe since the MacAddress struct is already sized to match the C sockaddr
416         // struct. The address family has also been checked.
417         Ok(unsafe { mem::transmute(ifreq.ifr_ifru.ifru_hwaddr) })
418     }
419 
set_mac_address(&self, mac_addr: MacAddress) -> Result<()>420     fn set_mac_address(&self, mac_addr: MacAddress) -> Result<()> {
421         let sock = create_socket()?;
422 
423         let mut ifreq = self.get_ifreq();
424 
425         // We only access one field of the ifru union, hence this is safe.
426         unsafe {
427             // This is safe since the MacAddress struct is already sized to match the C sockaddr
428             // struct.
429             ifreq.ifr_ifru.ifru_hwaddr = std::mem::transmute(mac_addr);
430         }
431 
432         // ioctl is safe. Called with a valid sock fd, and we check the return.
433         let ret =
434             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFHWADDR as IoctlNr, &ifreq) };
435         if ret < 0 {
436             return Err(Error::IoctlError(SysError::last()));
437         }
438 
439         Ok(())
440     }
441 
set_offload(&self, flags: c_uint) -> Result<()>442     fn set_offload(&self, flags: c_uint) -> Result<()> {
443         // ioctl is safe. Called with a valid tap fd, and we check the return.
444         let ret =
445             unsafe { ioctl_with_val(&self.tap_file, net_sys::TUNSETOFFLOAD(), flags as c_ulong) };
446         if ret < 0 {
447             return Err(Error::IoctlError(SysError::last()));
448         }
449 
450         Ok(())
451     }
452 
enable(&self) -> Result<()>453     fn enable(&self) -> Result<()> {
454         let sock = create_socket()?;
455 
456         let mut ifreq = self.get_ifreq();
457         ifreq.ifr_ifru.ifru_flags =
458             (net_sys::net_device_flags_IFF_UP | net_sys::net_device_flags_IFF_RUNNING) as i16;
459 
460         // ioctl is safe. Called with a valid sock fd, and we check the return.
461         let ret =
462             unsafe { ioctl_with_ref(&sock, net_sys::sockios::SIOCSIFFLAGS as IoctlNr, &ifreq) };
463         if ret < 0 {
464             return Err(Error::IoctlError(SysError::last()));
465         }
466 
467         Ok(())
468     }
469 
set_vnet_hdr_size(&self, size: c_int) -> Result<()>470     fn set_vnet_hdr_size(&self, size: c_int) -> Result<()> {
471         // ioctl is safe. Called with a valid tap fd, and we check the return.
472         let ret = unsafe { ioctl_with_ref(&self.tap_file, net_sys::TUNSETVNETHDRSZ(), &size) };
473         if ret < 0 {
474             return Err(Error::IoctlError(SysError::last()));
475         }
476 
477         Ok(())
478     }
479 
get_ifreq(&self) -> net_sys::ifreq480     fn get_ifreq(&self) -> net_sys::ifreq {
481         let mut ifreq: net_sys::ifreq = Default::default();
482 
483         // This sets the name of the interface, which is the only entry
484         // in a single-field union.
485         unsafe {
486             let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
487             ifrn_name.clone_from_slice(&self.if_name);
488         }
489 
490         // This sets the flags with which the interface was created, which is the only entry we set
491         // on the second union.
492         ifreq.ifr_ifru.ifru_flags = self.if_flags;
493 
494         ifreq
495     }
496 
if_flags(&self) -> u32497     fn if_flags(&self) -> u32 {
498         self.if_flags as u32
499     }
500 }
501 
502 impl Read for Tap {
read(&mut self, buf: &mut [u8]) -> IoResult<usize>503     fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
504         self.tap_file.read(buf)
505     }
506 }
507 
508 impl Write for Tap {
write(&mut self, buf: &[u8]) -> IoResult<usize>509     fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
510         self.tap_file.write(&buf)
511     }
512 
flush(&mut self) -> IoResult<()>513     fn flush(&mut self) -> IoResult<()> {
514         Ok(())
515     }
516 }
517 
518 impl AsRawFd for Tap {
as_raw_fd(&self) -> RawFd519     fn as_raw_fd(&self) -> RawFd {
520         self.tap_file.as_raw_descriptor()
521     }
522 }
523 
524 impl AsRawDescriptor for Tap {
as_raw_descriptor(&self) -> RawDescriptor525     fn as_raw_descriptor(&self) -> RawDescriptor {
526         self.tap_file.as_raw_descriptor()
527     }
528 }
529 
530 volatile_impl!(Tap);
531 
532 pub mod fakes {
533     use super::*;
534     use std::fs::remove_file;
535     use std::fs::OpenOptions;
536 
537     const TMP_FILE: &str = "/tmp/crosvm_tap_test_file";
538 
539     pub struct FakeTap {
540         tap_file: File,
541     }
542 
543     impl TapT for FakeTap {
new(_: bool, _: bool) -> Result<FakeTap>544         fn new(_: bool, _: bool) -> Result<FakeTap> {
545             Ok(FakeTap {
546                 tap_file: OpenOptions::new()
547                     .read(true)
548                     .append(true)
549                     .create(true)
550                     .open(TMP_FILE)
551                     .unwrap(),
552             })
553         }
554 
into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>>555         fn into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>> {
556             Ok(Vec::new())
557         }
558 
ip_addr(&self) -> Result<net::Ipv4Addr>559         fn ip_addr(&self) -> Result<net::Ipv4Addr> {
560             Ok(net::Ipv4Addr::new(1, 2, 3, 4))
561         }
562 
set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()>563         fn set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()> {
564             Ok(())
565         }
566 
netmask(&self) -> Result<net::Ipv4Addr>567         fn netmask(&self) -> Result<net::Ipv4Addr> {
568             Ok(net::Ipv4Addr::new(255, 255, 255, 252))
569         }
570 
set_netmask(&self, _: net::Ipv4Addr) -> Result<()>571         fn set_netmask(&self, _: net::Ipv4Addr) -> Result<()> {
572             Ok(())
573         }
574 
mac_address(&self) -> Result<MacAddress>575         fn mac_address(&self) -> Result<MacAddress> {
576             Ok("01:02:03:04:05:06".parse().unwrap())
577         }
578 
set_mac_address(&self, _: MacAddress) -> Result<()>579         fn set_mac_address(&self, _: MacAddress) -> Result<()> {
580             Ok(())
581         }
582 
set_offload(&self, _: c_uint) -> Result<()>583         fn set_offload(&self, _: c_uint) -> Result<()> {
584             Ok(())
585         }
586 
enable(&self) -> Result<()>587         fn enable(&self) -> Result<()> {
588             Ok(())
589         }
590 
set_vnet_hdr_size(&self, _: c_int) -> Result<()>591         fn set_vnet_hdr_size(&self, _: c_int) -> Result<()> {
592             Ok(())
593         }
594 
get_ifreq(&self) -> net_sys::ifreq595         fn get_ifreq(&self) -> net_sys::ifreq {
596             let ifreq: net_sys::ifreq = Default::default();
597             ifreq
598         }
599 
if_flags(&self) -> u32600         fn if_flags(&self) -> u32 {
601             net_sys::IFF_TAP
602         }
603     }
604 
605     impl Drop for FakeTap {
drop(&mut self)606         fn drop(&mut self) {
607             let _ = remove_file(TMP_FILE);
608         }
609     }
610 
611     impl Read for FakeTap {
read(&mut self, _: &mut [u8]) -> IoResult<usize>612         fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
613             Ok(0)
614         }
615     }
616 
617     impl Write for FakeTap {
write(&mut self, _: &[u8]) -> IoResult<usize>618         fn write(&mut self, _: &[u8]) -> IoResult<usize> {
619             Ok(0)
620         }
621 
flush(&mut self) -> IoResult<()>622         fn flush(&mut self) -> IoResult<()> {
623             Ok(())
624         }
625     }
626 
627     impl AsRawFd for FakeTap {
as_raw_fd(&self) -> RawFd628         fn as_raw_fd(&self) -> RawFd {
629             self.tap_file.as_raw_descriptor()
630         }
631     }
632 
633     impl AsRawDescriptor for FakeTap {
as_raw_descriptor(&self) -> RawDescriptor634         fn as_raw_descriptor(&self) -> RawDescriptor {
635             self.tap_file.as_raw_descriptor()
636         }
637     }
638     volatile_impl!(FakeTap);
639 }
640 
641 #[cfg(test)]
642 mod tests {
643     use super::*;
644 
645     #[test]
parse_mac_address()646     fn parse_mac_address() {
647         assert!("01:02:03:04:05:06".parse::<MacAddress>().is_ok());
648         assert!("01:06".parse::<MacAddress>().is_err());
649         assert!("01:02:03:04:05:06:07:08:09".parse::<MacAddress>().is_err());
650         assert!("not a mac address".parse::<MacAddress>().is_err());
651     }
652 
653     #[test]
tap_create()654     fn tap_create() {
655         Tap::new(true, false).unwrap();
656     }
657 
658     #[test]
tap_configure()659     fn tap_configure() {
660         let tap = Tap::new(true, false).unwrap();
661         let ip_addr: net::Ipv4Addr = "100.115.92.5".parse().unwrap();
662         let netmask: net::Ipv4Addr = "255.255.255.252".parse().unwrap();
663         let mac_addr: MacAddress = "a2:06:b9:3d:68:4d".parse().unwrap();
664 
665         let ret = tap.set_ip_addr(ip_addr);
666         assert_ok_or_perm_denied(ret);
667         let ret = tap.set_netmask(netmask);
668         assert_ok_or_perm_denied(ret);
669         let ret = tap.set_mac_address(mac_addr);
670         assert_ok_or_perm_denied(ret);
671     }
672 
673     /// This test will only work if the test is run with root permissions and, unlike other tests
674     /// in this file, do not return PermissionDenied. They fail because the TAP FD is not
675     /// initialized (as opposed to permission denial). Run this with "cargo test -- --ignored".
676     #[test]
677     #[ignore]
root_only_tests()678     fn root_only_tests() {
679         // This line will fail to provide an initialized FD if the test is not run as root.
680         let tap = Tap::new(true, false).unwrap();
681         tap.set_vnet_hdr_size(16).unwrap();
682         tap.set_offload(0).unwrap();
683     }
684 
685     #[test]
tap_enable()686     fn tap_enable() {
687         let tap = Tap::new(true, false).unwrap();
688 
689         let ret = tap.enable();
690         assert_ok_or_perm_denied(ret);
691     }
692 
assert_ok_or_perm_denied<T>(res: Result<T>)693     fn assert_ok_or_perm_denied<T>(res: Result<T>) {
694         match res {
695             // We won't have permission in test environments; allow that
696             Ok(_t) => {}
697             Err(Error::IoctlError(e)) if e.errno() == EPERM => {}
698             Err(e) => panic!("Unexpected Error:\n{}", e),
699         }
700     }
701 }
702