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) unsafe fn borrow_raw(fd: RawFd) -> io::Result<Self> {
49 let tun = Fd::new_unchecked_with_borrow(fd, true);
50 DeviceImpl::from_tun(Tun::new(tun))
51 }
52 pub(crate) fn is_nonblocking(&self) -> io::Result<bool> {
53 self.tun.is_nonblocking()
54 }
55 pub(crate) fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
57 self.tun.set_nonblocking(nonblocking)
58 }
59
60 pub(crate) fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
62 self.tun.recv(buf)
63 }
64 pub(crate) fn recv_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
65 self.tun.recv_vectored(bufs)
66 }
67
68 pub(crate) fn send(&self, buf: &[u8]) -> io::Result<usize> {
70 self.tun.send(buf)
71 }
72 pub(crate) fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
73 self.tun.send_vectored(bufs)
74 }
75 #[cfg(feature = "interruptible")]
76 pub(crate) fn read_interruptible(
77 &self,
78 buf: &mut [u8],
79 event: &crate::InterruptEvent,
80 ) -> io::Result<usize> {
81 self.tun.read_interruptible(buf, event)
82 }
83 #[cfg(feature = "interruptible")]
84 pub(crate) fn readv_interruptible(
85 &self,
86 bufs: &mut [IoSliceMut<'_>],
87 event: &crate::InterruptEvent,
88 ) -> io::Result<usize> {
89 self.tun.readv_interruptible(bufs, event)
90 }
91 #[cfg(feature = "interruptible")]
92 #[inline]
93 pub(crate) fn wait_readable_interruptible(
94 &self,
95 event: &crate::InterruptEvent,
96 ) -> io::Result<()> {
97 self.tun.wait_readable_interruptible(event)
98 }
99 #[cfg(feature = "interruptible")]
100 pub(crate) fn write_interruptible(
101 &self,
102 buf: &[u8],
103 event: &crate::InterruptEvent,
104 ) -> io::Result<usize> {
105 self.tun.write_interruptible(buf, event)
106 }
107 #[cfg(feature = "interruptible")]
108 #[inline]
109 pub(crate) fn writev_interruptible(
110 &self,
111 bufs: &[IoSlice<'_>],
112 event: &crate::InterruptEvent,
113 ) -> io::Result<usize> {
114 self.tun.writev_interruptible(bufs, event)
115 }
116 #[cfg(feature = "interruptible")]
117 #[inline]
118 pub(crate) fn wait_writable_interruptible(
119 &self,
120 event: &crate::InterruptEvent,
121 ) -> io::Result<()> {
122 self.tun.wait_writable_interruptible(event)
123 }
124}
125#[cfg(any(
126 all(target_os = "linux", not(target_env = "ohos")),
127 target_os = "macos",
128 target_os = "freebsd",
129 target_os = "openbsd",
130 target_os = "netbsd",
131))]
132impl DeviceImpl {
133 pub fn if_index(&self) -> io::Result<u32> {
139 let _guard = self.op_lock.lock().unwrap();
140 self.if_index_impl()
141 }
142 pub(crate) fn if_index_impl(&self) -> io::Result<u32> {
143 let if_name = std::ffi::CString::new(self.name_impl()?)?;
144 unsafe { Ok(libc::if_nametoindex(if_name.as_ptr())) }
145 }
146 pub fn addresses(&self) -> io::Result<Vec<std::net::IpAddr>> {
152 Ok(crate::platform::get_if_addrs_by_name(self.name_impl()?)?
153 .iter()
154 .map(|v| v.address)
155 .collect())
156 }
157}
158#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos",))]
159impl DeviceImpl {
160 pub fn ignore_packet_info(&self) -> bool {
171 let _guard = self.op_lock.lock().unwrap();
172 self.tun.ignore_packet_info()
173 }
174 pub fn set_ignore_packet_info(&self, ign: bool) {
186 let _guard = self.op_lock.lock().unwrap();
187 self.tun.set_ignore_packet_info(ign)
188 }
189}
190#[cfg(any(
191 all(target_os = "linux", not(target_env = "ohos")),
192 target_os = "freebsd",
193 target_os = "openbsd",
194 target_os = "netbsd",
195))]
196pub(crate) unsafe fn ctl() -> io::Result<Fd> {
197 Fd::new(libc::socket(AF_INET, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
198}
199#[cfg(target_os = "macos")]
200pub(crate) unsafe fn ctl() -> io::Result<Fd> {
201 let fd = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0))?;
202 _ = fd.set_cloexec();
203 Ok(fd)
204}
205#[cfg(any(
206 all(target_os = "linux", not(target_env = "ohos")),
207 target_os = "freebsd",
208 target_os = "openbsd",
209 target_os = "netbsd",
210))]
211pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
212 Fd::new(libc::socket(AF_INET6, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
213}
214#[cfg(target_os = "macos")]
215pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
216 let fd = Fd::new(libc::socket(AF_INET6, SOCK_DGRAM, 0))?;
217 _ = fd.set_cloexec();
218 Ok(fd)
219}