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