1use std::fs::File;
6use std::io::Read;
7use std::io::Result as IoResult;
8use std::io::Write;
9use std::mem;
10use std::net;
11use std::os::raw::*;
12use std::os::unix::io::AsRawFd;
13use std::os::unix::io::FromRawFd;
14use std::os::unix::io::RawFd;
15
16use base::add_fd_flags;
17use base::error;
18use base::ioctl_with_mut_ref;
19use base::ioctl_with_ref;
20use base::ioctl_with_val;
21use base::volatile_impl;
22use base::warn;
23use base::AsRawDescriptor;
24use base::Error as SysError;
25use base::FileReadWriteVolatile;
26use base::FromRawDescriptor;
27use base::IoctlNr;
28use base::RawDescriptor;
29use base::ReadNotifier;
30use cros_async::IntoAsync;
31
32use crate::sys::linux::TapTLinux;
33use crate::Error;
34use crate::MacAddress;
35use crate::Result;
36use crate::TapT;
37use crate::TapTCommon;
38
39#[derive(Debug)]
46pub struct Tap {
47 tap_file: File,
48 if_name: [c_char; 16usize],
49 if_flags: ::std::os::raw::c_short,
50}
51
52impl Tap {
53 pub unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Tap> {
57 let tap_file = File::from_raw_descriptor(descriptor);
58
59 add_fd_flags(tap_file.as_raw_descriptor(), libc::O_NONBLOCK).map_err(Error::IoctlError)?;
62
63 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
78 pub fn create_tap_with_ifreq(ifreq: &mut net_sys::ifreq) -> Result<Tap> {
79 let rd = unsafe {
83 libc::open64(
84 c"/dev/net/tun".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 let tuntap = unsafe { File::from_raw_descriptor(rd) };
95 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 if_name: unsafe { ifreq.ifr_ifrn.ifrn_name },
109 if_flags: unsafe { ifreq.ifr_ifru.ifru_flags },
112 })
113 }
114
115 fn get_ifreq(&self) -> net_sys::ifreq {
116 let mut ifreq: net_sys::ifreq = Default::default();
117
118 unsafe {
122 let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
123 ifrn_name.clone_from_slice(&self.if_name);
124 }
125
126 ifreq.ifr_ifru.ifru_flags = self.if_flags;
129
130 ifreq
131 }
132
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
146impl TapTCommon for Tap {
147 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
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 unsafe {
165 let ifrn_name = ifreq.ifr_ifrn.ifrn_name.as_mut();
166 for (dst, src) in ifrn_name
167 .iter_mut()
168 .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
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 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
206 fn ip_addr(&self) -> Result<net::Ipv4Addr> {
207 let sock = create_socket()?;
208 let mut ifreq = self.get_ifreq();
209
210 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 let addr = unsafe { ifreq.ifr_ifru.ifru_addr };
223
224 Ok(read_ipv4_addr(&addr))
225 }
226
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 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
245 fn netmask(&self) -> Result<net::Ipv4Addr> {
246 let sock = create_socket()?;
247 let mut ifreq = self.get_ifreq();
248
249 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 let addr = unsafe { ifreq.ifr_ifru.ifru_netmask };
265
266 Ok(read_ipv4_addr(&addr))
267 }
268
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 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
287 fn mtu(&self) -> Result<u16> {
288 let sock = create_socket()?;
289 let mut ifreq = self.get_ifreq();
290
291 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 let mtu = unsafe { ifreq.ifr_ifru.ifru_mtu } as u16;
303 Ok(mtu)
304 }
305
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 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
322 fn mac_address(&self) -> Result<MacAddress> {
323 let sock = create_socket()?;
324 let mut ifreq = self.get_ifreq();
325
326 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 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)] 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
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)] 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 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
388 fn set_offload(&self, flags: c_uint) -> Result<()> {
389 let ret =
390 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
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 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
418 fn try_clone(&self) -> Result<Self> {
419 self.try_clone()
420 }
421
422 unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self> {
425 Tap::from_raw_descriptor(descriptor)
426 }
427}
428
429impl TapTLinux for Tap {
430 fn set_vnet_hdr_size(&self, size: usize) -> Result<()> {
431 let size = size as c_int;
432 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
442 fn if_flags(&self) -> u32 {
443 self.if_flags as u32
444 }
445}
446
447impl Read for Tap {
448 fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
449 self.tap_file.read(buf)
450 }
451}
452
453impl Write for Tap {
454 fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
455 self.tap_file.write(buf)
456 }
457
458 fn flush(&mut self) -> IoResult<()> {
459 Ok(())
460 }
461}
462
463impl AsRawFd for Tap {
464 fn as_raw_fd(&self) -> RawFd {
465 self.tap_file.as_raw_descriptor()
466 }
467}
468
469impl AsRawDescriptor for Tap {
470 fn as_raw_descriptor(&self) -> RawDescriptor {
471 self.tap_file.as_raw_descriptor()
472 }
473}
474
475impl ReadNotifier for Tap {
476 fn get_read_notifier(&self) -> &dyn AsRawDescriptor {
477 self
478 }
479}
480
481fn create_socket() -> Result<net::UdpSocket> {
482 let sock = unsafe { libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0) };
485 if sock >= 0 {
486 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 let sock6 = unsafe { libc::socket(libc::AF_INET6, libc::SOCK_DGRAM, 0) };
496 if sock6 >= 0 {
497 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
507fn 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 unsafe { mem::transmute::<libc::sockaddr_in, libc::sockaddr>(addr_in) }
515}
516
517fn 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 Some(unsafe { mem::transmute::<libc::sockaddr, libc::sockaddr_in>(addr) })
531}
532
533fn 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 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
553fn 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
559impl TapT for Tap {}
560impl IntoAsync for Tap {}
561volatile_impl!(Tap);
562
563pub 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 {
576 fn new(_vnet_hdr: bool, _multi_vq: bool) -> Result<Self> {
577 Self::new_with_name(b"", false, false)
579 }
580
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
592 fn into_mq_taps(self, _vq_pairs: u16) -> Result<Vec<FakeTap>> {
593 Ok(Vec::new())
594 }
595
596 fn ip_addr(&self) -> Result<net::Ipv4Addr> {
597 Ok(net::Ipv4Addr::new(1, 2, 3, 4))
598 }
599
600 fn set_ip_addr(&self, _: net::Ipv4Addr) -> Result<()> {
601 Ok(())
602 }
603
604 fn netmask(&self) -> Result<net::Ipv4Addr> {
605 Ok(net::Ipv4Addr::new(255, 255, 255, 252))
606 }
607
608 fn set_netmask(&self, _: net::Ipv4Addr) -> Result<()> {
609 Ok(())
610 }
611
612 fn mtu(&self) -> Result<u16> {
613 Ok(1500)
614 }
615
616 fn set_mtu(&self, _: u16) -> Result<()> {
617 Ok(())
618 }
619
620 fn mac_address(&self) -> Result<MacAddress> {
621 Ok("01:02:03:04:05:06".parse().unwrap())
622 }
623
624 fn set_mac_address(&self, _: MacAddress) -> Result<()> {
625 Ok(())
626 }
627
628 fn set_offload(&self, _: c_uint) -> Result<()> {
629 Ok(())
630 }
631
632 fn enable(&self) -> Result<()> {
633 Ok(())
634 }
635
636 fn try_clone(&self) -> Result<Self> {
638 Ok(FakeTap {
639 tap_file: self.tap_file.try_clone().unwrap(),
640 })
641 }
642
643 unsafe fn from_raw_descriptor(_descriptor: RawDescriptor) -> Result<Self> {
644 unimplemented!()
645 }
646 }
647
648 impl TapTLinux for FakeTap {
649 fn set_vnet_hdr_size(&self, _: usize) -> Result<()> {
650 Ok(())
651 }
652
653 fn if_flags(&self) -> u32 {
654 net_sys::IFF_TAP
655 }
656 }
657
658 impl Drop for FakeTap {
659 fn drop(&mut self) {
660 let _ = remove_file(TMP_FILE);
661 }
662 }
663
664 impl Read for FakeTap {
665 fn read(&mut self, _: &mut [u8]) -> IoResult<usize> {
666 Ok(0)
667 }
668 }
669
670 impl Write for FakeTap {
671 fn write(&mut self, _: &[u8]) -> IoResult<usize> {
672 Ok(0)
673 }
674
675 fn flush(&mut self) -> IoResult<()> {
676 Ok(())
677 }
678 }
679
680 impl AsRawFd for FakeTap {
681 fn as_raw_fd(&self) -> RawFd {
682 self.tap_file.as_raw_descriptor()
683 }
684 }
685
686 impl AsRawDescriptor for FakeTap {
687 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)]
696pub mod tests {
697 use super::*;
698
699 #[test]
700 fn sockaddr_byte_order() {
701 let sa = create_sockaddr(net::Ipv4Addr::new(1, 2, 3, 4));
702 assert_eq!(sa.sa_family, 2); assert_eq!(
704 sa.sa_data,
705 [
706 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, ]
710 );
711 }
712}