ya_smoltcp/phy/sys/
tuntap_interface.rs1use super::*;
2use crate::{phy::Medium, wire::EthernetFrame};
3use std::io;
4use std::os::unix::io::{AsRawFd, RawFd};
5
6#[derive(Debug)]
7pub struct TunTapInterfaceDesc {
8 lower: libc::c_int,
9 ifreq: ifreq,
10 medium: Medium,
11}
12
13impl AsRawFd for TunTapInterfaceDesc {
14 fn as_raw_fd(&self) -> RawFd {
15 self.lower
16 }
17}
18
19impl TunTapInterfaceDesc {
20 pub fn new(name: &str, medium: Medium) -> io::Result<TunTapInterfaceDesc> {
21 let lower = unsafe {
22 let lower = libc::open(
23 "/dev/net/tun\0".as_ptr() as *const libc::c_char,
24 libc::O_RDWR | libc::O_NONBLOCK,
25 );
26 if lower == -1 {
27 return Err(io::Error::last_os_error());
28 }
29 lower
30 };
31
32 Ok(TunTapInterfaceDesc {
33 lower,
34 ifreq: ifreq_for(name),
35 medium,
36 })
37 }
38
39 pub fn attach_interface(&mut self) -> io::Result<()> {
40 let mode = match self.medium {
41 #[cfg(feature = "medium-ip")]
42 Medium::Ip => imp::IFF_TUN,
43 #[cfg(feature = "medium-ethernet")]
44 Medium::Ethernet => imp::IFF_TAP,
45 #[cfg(feature = "medium-ieee802154")]
46 Medium::Ieee802154 => todo!(),
47 };
48 self.ifreq.ifr_data = mode | imp::IFF_NO_PI;
49 ifreq_ioctl(self.lower, &mut self.ifreq, imp::TUNSETIFF).map(|_| ())
50 }
51
52 pub fn interface_mtu(&mut self) -> io::Result<usize> {
53 let lower = unsafe {
54 let lower = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP);
55 if lower == -1 {
56 return Err(io::Error::last_os_error());
57 }
58 lower
59 };
60
61 let ip_mtu = ifreq_ioctl(lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize);
62
63 unsafe {
64 libc::close(lower);
65 }
66
67 let ip_mtu = ip_mtu?;
69
70 let mtu = match self.medium {
73 #[cfg(feature = "medium-ip")]
74 Medium::Ip => ip_mtu,
75 #[cfg(feature = "medium-ethernet")]
76 Medium::Ethernet => ip_mtu + EthernetFrame::<&[u8]>::header_len(),
77 #[cfg(feature = "medium-ieee802154")]
78 Medium::Ieee802154 => todo!(),
79 };
80
81 Ok(mtu)
82 }
83
84 pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
85 unsafe {
86 let len = libc::read(
87 self.lower,
88 buffer.as_mut_ptr() as *mut libc::c_void,
89 buffer.len(),
90 );
91 if len == -1 {
92 return Err(io::Error::last_os_error());
93 }
94 Ok(len as usize)
95 }
96 }
97
98 pub fn send(&mut self, buffer: &[u8]) -> io::Result<usize> {
99 unsafe {
100 let len = libc::write(
101 self.lower,
102 buffer.as_ptr() as *const libc::c_void,
103 buffer.len(),
104 );
105 if len == -1 {
106 Err(io::Error::last_os_error()).unwrap()
107 }
108 Ok(len as usize)
109 }
110 }
111}
112
113impl Drop for TunTapInterfaceDesc {
114 fn drop(&mut self) {
115 unsafe {
116 libc::close(self.lower);
117 }
118 }
119}