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