tun_rs/platform/unix/
device.rs1use crate::platform::unix::{Fd, Tun};
2use crate::platform::DeviceImpl;
3#[cfg(any(
4 all(target_os = "linux", not(target_env = "ohos")),
5 target_os = "macos",
6 target_os = "freebsd",
7 target_os = "openbsd",
8 target_os = "netbsd",
9))]
10use libc::{AF_INET, AF_INET6, SOCK_DGRAM};
11use std::io;
12use std::io::{IoSlice, IoSliceMut};
13use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
14
15impl FromRawFd for DeviceImpl {
16 unsafe fn from_raw_fd(fd: RawFd) -> Self {
17 DeviceImpl::from_fd(fd).unwrap()
18 }
19}
20impl AsRawFd for DeviceImpl {
21 fn as_raw_fd(&self) -> RawFd {
22 self.tun.as_raw_fd()
23 }
24}
25impl AsFd for DeviceImpl {
26 fn as_fd(&self) -> BorrowedFd<'_> {
27 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
28 }
29}
30#[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
31impl std::os::unix::io::IntoRawFd for DeviceImpl {
32 fn into_raw_fd(self) -> RawFd {
33 self.tun.into_raw_fd()
34 }
35}
36impl DeviceImpl {
37 pub(crate) unsafe fn from_fd(fd: RawFd) -> io::Result<Self> {
40 let tun = Fd::new_unchecked(fd);
41 DeviceImpl::from_tun(Tun::new(tun))
42 }
43 pub(crate) fn is_nonblocking(&self) -> io::Result<bool> {
44 self.tun.is_nonblocking()
45 }
46 pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
48 self.tun.set_nonblocking(nonblocking)
49 }
50
51 pub(crate) fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
53 self.tun.recv(buf)
54 }
55 pub(crate) fn recv_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
56 self.tun.recv_vectored(bufs)
57 }
58
59 pub(crate) fn send(&self, buf: &[u8]) -> io::Result<usize> {
61 self.tun.send(buf)
62 }
63 pub(crate) fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
64 self.tun.send_vectored(bufs)
65 }
66 #[cfg(feature = "interruptible")]
67 pub(crate) fn read_interruptible(
68 &self,
69 buf: &mut [u8],
70 event: &crate::InterruptEvent,
71 ) -> io::Result<usize> {
72 self.tun.read_interruptible(buf, event)
73 }
74 #[cfg(feature = "interruptible")]
75 pub(crate) fn readv_interruptible(
76 &self,
77 bufs: &mut [IoSliceMut<'_>],
78 event: &crate::InterruptEvent,
79 ) -> io::Result<usize> {
80 self.tun.readv_interruptible(bufs, event)
81 }
82 #[cfg(feature = "interruptible")]
83 #[inline]
84 pub(crate) fn wait_readable_interruptible(
85 &self,
86 event: &crate::InterruptEvent,
87 ) -> io::Result<()> {
88 self.tun.wait_readable_interruptible(event)
89 }
90 #[cfg(feature = "interruptible")]
91 pub(crate) fn write_interruptible(
92 &self,
93 buf: &[u8],
94 event: &crate::InterruptEvent,
95 ) -> io::Result<usize> {
96 self.tun.write_interruptible(buf, event)
97 }
98 #[cfg(feature = "interruptible")]
99 #[inline]
100 pub(crate) fn writev_interruptible(
101 &self,
102 bufs: &[IoSlice<'_>],
103 event: &crate::InterruptEvent,
104 ) -> io::Result<usize> {
105 self.tun.writev_interruptible(bufs, event)
106 }
107 #[cfg(feature = "interruptible")]
108 #[inline]
109 pub(crate) fn wait_writable_interruptible(
110 &self,
111 event: &crate::InterruptEvent,
112 ) -> io::Result<()> {
113 self.tun.wait_writable_interruptible(event)
114 }
115}
116#[cfg(any(
117 all(target_os = "linux", not(target_env = "ohos")),
118 target_os = "macos",
119 target_os = "freebsd",
120 target_os = "openbsd",
121 target_os = "netbsd",
122))]
123impl DeviceImpl {
124 pub fn if_index(&self) -> io::Result<u32> {
130 let _guard = self.op_lock.lock().unwrap();
131 self.if_index_impl()
132 }
133 pub(crate) fn if_index_impl(&self) -> io::Result<u32> {
134 let if_name = std::ffi::CString::new(self.name_impl()?)?;
135 unsafe { Ok(libc::if_nametoindex(if_name.as_ptr())) }
136 }
137 pub fn addresses(&self) -> io::Result<Vec<std::net::IpAddr>> {
143 Ok(crate::platform::get_if_addrs_by_name(self.name_impl()?)?
144 .iter()
145 .map(|v| v.address)
146 .collect())
147 }
148}
149#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos",))]
150impl DeviceImpl {
151 pub fn ignore_packet_info(&self) -> bool {
162 let _guard = self.op_lock.lock().unwrap();
163 self.tun.ignore_packet_info()
164 }
165 pub fn set_ignore_packet_info(&self, ign: bool) {
177 let _guard = self.op_lock.lock().unwrap();
178 self.tun.set_ignore_packet_info(ign)
179 }
180}
181#[cfg(any(
182 all(target_os = "linux", not(target_env = "ohos")),
183 target_os = "freebsd",
184 target_os = "openbsd",
185 target_os = "netbsd",
186))]
187pub(crate) unsafe fn ctl() -> io::Result<Fd> {
188 Fd::new(libc::socket(AF_INET, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
189}
190#[cfg(target_os = "macos")]
191pub(crate) unsafe fn ctl() -> io::Result<Fd> {
192 let fd = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0))?;
193 _ = fd.set_cloexec();
194 Ok(fd)
195}
196#[cfg(any(
197 all(target_os = "linux", not(target_env = "ohos")),
198 target_os = "freebsd",
199 target_os = "openbsd",
200 target_os = "netbsd",
201))]
202pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
203 Fd::new(libc::socket(AF_INET6, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
204}
205#[cfg(target_os = "macos")]
206pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
207 let fd = Fd::new(libc::socket(AF_INET6, SOCK_DGRAM, 0))?;
208 _ = fd.set_cloexec();
209 Ok(fd)
210}