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 timeout: Option<std::time::Duration>,
81 ) -> io::Result<usize> {
82 self.tun.read_interruptible(buf, event, timeout)
83 }
84 #[cfg(feature = "interruptible")]
85 pub(crate) fn readv_interruptible(
86 &self,
87 bufs: &mut [IoSliceMut<'_>],
88 event: &crate::InterruptEvent,
89 timeout: Option<std::time::Duration>,
90 ) -> io::Result<usize> {
91 self.tun.readv_interruptible(bufs, event, timeout)
92 }
93 #[cfg(feature = "interruptible")]
94 #[inline]
95 pub(crate) fn wait_readable_interruptible(
96 &self,
97 event: &crate::InterruptEvent,
98 timeout: Option<std::time::Duration>,
99 ) -> io::Result<()> {
100 self.tun.wait_readable_interruptible(event, timeout)
101 }
102 #[cfg(feature = "interruptible")]
103 pub(crate) fn write_interruptible(
104 &self,
105 buf: &[u8],
106 event: &crate::InterruptEvent,
107 ) -> io::Result<usize> {
108 self.tun.write_interruptible(buf, event)
109 }
110 #[cfg(feature = "interruptible")]
111 #[inline]
112 pub(crate) fn writev_interruptible(
113 &self,
114 bufs: &[IoSlice<'_>],
115 event: &crate::InterruptEvent,
116 ) -> io::Result<usize> {
117 self.tun.writev_interruptible(bufs, event)
118 }
119 #[cfg(feature = "interruptible")]
120 #[inline]
121 pub(crate) fn wait_writable_interruptible(
122 &self,
123 event: &crate::InterruptEvent,
124 ) -> io::Result<()> {
125 self.tun.wait_writable_interruptible(event)
126 }
127}
128#[cfg(any(
129 all(target_os = "linux", not(target_env = "ohos")),
130 target_os = "macos",
131 target_os = "freebsd",
132 target_os = "openbsd",
133 target_os = "netbsd",
134))]
135impl DeviceImpl {
136 pub fn if_index(&self) -> io::Result<u32> {
142 let _guard = self.op_lock.lock().unwrap();
143 self.if_index_impl()
144 }
145 pub(crate) fn if_index_impl(&self) -> io::Result<u32> {
146 let if_name = std::ffi::CString::new(self.name_impl()?)?;
147 unsafe { Ok(libc::if_nametoindex(if_name.as_ptr())) }
148 }
149 pub fn addresses(&self) -> io::Result<Vec<std::net::IpAddr>> {
155 Ok(crate::platform::get_if_addrs_by_name(self.name_impl()?)?
156 .iter()
157 .map(|v| v.address)
158 .collect())
159 }
160}
161#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos",))]
162impl DeviceImpl {
163 pub fn ignore_packet_info(&self) -> bool {
174 let _guard = self.op_lock.lock().unwrap();
175 self.tun.ignore_packet_info()
176 }
177 pub fn set_ignore_packet_info(&self, ign: bool) {
189 let _guard = self.op_lock.lock().unwrap();
190 self.tun.set_ignore_packet_info(ign)
191 }
192}
193#[cfg(any(
194 all(target_os = "linux", not(target_env = "ohos")),
195 target_os = "freebsd",
196 target_os = "openbsd",
197 target_os = "netbsd",
198))]
199pub(crate) unsafe fn ctl() -> io::Result<Fd> {
200 Fd::new(libc::socket(AF_INET, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
201}
202#[cfg(target_os = "macos")]
203pub(crate) unsafe fn ctl() -> io::Result<Fd> {
204 let fd = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0))?;
205 _ = fd.set_cloexec();
206 Ok(fd)
207}
208#[cfg(any(
209 all(target_os = "linux", not(target_env = "ohos")),
210 target_os = "freebsd",
211 target_os = "openbsd",
212 target_os = "netbsd",
213))]
214pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
215 Fd::new(libc::socket(AF_INET6, SOCK_DGRAM | libc::SOCK_CLOEXEC, 0))
216}
217#[cfg(target_os = "macos")]
218pub(crate) unsafe fn ctl_v6() -> io::Result<Fd> {
219 let fd = Fd::new(libc::socket(AF_INET6, SOCK_DGRAM, 0))?;
220 _ = fd.set_cloexec();
221 Ok(fd)
222}