1#[cfg(unix)]
2pub(crate) mod unix;
3
4#[cfg(all(
5 unix,
6 not(any(
7 target_os = "windows",
8 target_os = "macos",
9 all(target_os = "linux", not(target_env = "ohos")),
10 target_os = "freebsd",
11 target_os = "openbsd",
12 target_os = "netbsd",
13 ))
14))]
15pub use self::unix::DeviceImpl;
16#[cfg(unix)]
17#[cfg(feature = "interruptible")]
18pub use unix::InterruptEvent;
19#[cfg(windows)]
20#[cfg(feature = "interruptible")]
21pub use windows::InterruptEvent;
22#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
23pub(crate) mod linux;
24#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
25pub use self::linux::*;
26
27#[cfg(target_os = "freebsd")]
28pub(crate) mod freebsd;
29#[cfg(target_os = "freebsd")]
30pub use self::freebsd::DeviceImpl;
31
32#[cfg(target_os = "macos")]
33pub(crate) mod macos;
34#[cfg(target_os = "macos")]
35pub use self::macos::DeviceImpl;
36#[cfg(target_os = "openbsd")]
37pub(crate) mod openbsd;
38#[cfg(target_os = "openbsd")]
39pub use self::openbsd::DeviceImpl;
40
41#[cfg(target_os = "netbsd")]
42pub(crate) mod netbsd;
43#[cfg(target_os = "netbsd")]
44pub use self::netbsd::DeviceImpl;
45
46#[cfg(target_os = "windows")]
47pub(crate) mod windows;
48#[cfg(target_os = "windows")]
49pub use self::windows::DeviceImpl;
50
51use getifaddrs::Interface;
52#[cfg(unix)]
53use std::io::{IoSlice, IoSliceMut};
54use std::ops::Deref;
55#[cfg(unix)]
56use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
57
58#[allow(dead_code)]
59pub(crate) const ETHER_ADDR_LEN: u8 = 6;
60
61#[allow(dead_code)]
62pub(crate) fn get_if_addrs_by_name(if_name: String) -> std::io::Result<Vec<Interface>> {
63 let addrs = getifaddrs::getifaddrs()?;
64 let ifs = addrs.filter(|v| v.name == if_name).collect();
65 Ok(ifs)
66}
67
68#[repr(transparent)]
100pub struct SyncDevice(pub(crate) DeviceImpl);
101
102impl SyncDevice {
103 #[cfg(unix)]
111 pub unsafe fn from_fd(fd: RawFd) -> std::io::Result<Self> {
112 Ok(SyncDevice(DeviceImpl::from_fd(fd)?))
113 }
114 #[cfg(unix)]
120 pub(crate) unsafe fn borrow_raw(fd: RawFd) -> std::io::Result<Self> {
121 Ok(SyncDevice(DeviceImpl::borrow_raw(fd)?))
122 }
123 pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
142 self.0.recv(buf)
143 }
144 pub fn send(&self, buf: &[u8]) -> std::io::Result<usize> {
160 self.0.send(buf)
161 }
162 #[cfg(target_os = "windows")]
166 pub fn try_recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
167 self.0.try_recv(buf)
168 }
169 #[cfg(target_os = "windows")]
173 pub fn try_send(&self, buf: &[u8]) -> std::io::Result<usize> {
174 self.0.try_send(buf)
175 }
176 #[cfg(target_os = "windows")]
180 pub fn shutdown(&self) -> std::io::Result<()> {
181 self.0.shutdown()
182 }
183 #[cfg(all(unix, feature = "experimental"))]
184 pub fn shutdown(&self) -> std::io::Result<()> {
185 Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
186 }
187 #[cfg(feature = "interruptible")]
212 pub fn recv_intr(&self, buf: &mut [u8], event: &InterruptEvent) -> std::io::Result<usize> {
213 self.0.read_interruptible(buf, event, None)
214 }
215 #[cfg(feature = "interruptible")]
216 pub fn recv_intr_timeout(
217 &self,
218 buf: &mut [u8],
219 event: &InterruptEvent,
220 timeout: Option<std::time::Duration>,
221 ) -> std::io::Result<usize> {
222 self.0.read_interruptible(buf, event, timeout)
223 }
224 #[cfg(all(unix, feature = "interruptible"))]
233 pub fn recv_vectored_intr(
234 &self,
235 bufs: &mut [IoSliceMut<'_>],
236 event: &InterruptEvent,
237 ) -> std::io::Result<usize> {
238 self.0.readv_interruptible(bufs, event, None)
239 }
240 #[cfg(all(unix, feature = "interruptible"))]
241 pub fn recv_vectored_intr_timeout(
242 &self,
243 bufs: &mut [IoSliceMut<'_>],
244 event: &InterruptEvent,
245 timeout: Option<std::time::Duration>,
246 ) -> std::io::Result<usize> {
247 self.0.readv_interruptible(bufs, event, timeout)
248 }
249 #[cfg(feature = "interruptible")]
250 pub fn wait_readable_intr(&self, event: &InterruptEvent) -> std::io::Result<()> {
251 self.0.wait_readable_interruptible(event, None)
252 }
253 #[cfg(feature = "interruptible")]
254 pub fn wait_readable_intr_timeout(
255 &self,
256 event: &InterruptEvent,
257 timeout: Option<std::time::Duration>,
258 ) -> std::io::Result<()> {
259 self.0.wait_readable_interruptible(event, timeout)
260 }
261 #[cfg(feature = "interruptible")]
262 pub fn send_intr(&self, buf: &[u8], event: &InterruptEvent) -> std::io::Result<usize> {
263 self.0.write_interruptible(buf, event)
264 }
265 #[cfg(all(unix, feature = "interruptible"))]
266 pub fn send_vectored_intr(
267 &self,
268 bufs: &[IoSlice<'_>],
269 event: &InterruptEvent,
270 ) -> std::io::Result<usize> {
271 self.0.writev_interruptible(bufs, event)
272 }
273 #[cfg(all(unix, feature = "interruptible"))]
274 #[inline]
275 pub fn wait_writable_intr(&self, event: &InterruptEvent) -> std::io::Result<()> {
276 self.0.wait_writable_interruptible(event)
277 }
278 #[cfg(unix)]
285 pub fn recv_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
286 self.0.recv_vectored(bufs)
287 }
288 #[cfg(unix)]
295 pub fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
296 self.0.send_vectored(bufs)
297 }
298 #[cfg(unix)]
302 pub fn is_nonblocking(&self) -> std::io::Result<bool> {
303 self.0.is_nonblocking()
304 }
305
306 #[cfg(unix)]
312 pub fn set_nonblocking(&self, nonblocking: bool) -> std::io::Result<()> {
313 self.0.set_nonblocking(nonblocking)
314 }
315
316 #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
323 pub fn try_clone(&self) -> std::io::Result<SyncDevice> {
324 let device_impl = self.0.try_clone()?;
325 Ok(SyncDevice(device_impl))
326 }
327}
328#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
329impl SyncDevice {
330 #[cfg(feature = "interruptible")]
331 pub fn send_multiple_intr<B: ExpandBuffer>(
332 &self,
333 gro_table: &mut GROTable,
334 bufs: &mut [B],
335 offset: usize,
336 event: &InterruptEvent,
337 ) -> std::io::Result<usize> {
338 self.send_multiple0(gro_table, bufs, offset, |tun, buf| {
339 tun.write_interruptible(buf, event)
340 })
341 }
342 #[cfg(feature = "interruptible")]
343 pub fn recv_multiple_intr<B: AsRef<[u8]> + AsMut<[u8]>>(
344 &self,
345 original_buffer: &mut [u8],
346 bufs: &mut [B],
347 sizes: &mut [usize],
348 offset: usize,
349 event: &InterruptEvent,
350 ) -> std::io::Result<usize> {
351 self.recv_multiple0(original_buffer, bufs, sizes, offset, |tun, buf| {
352 tun.read_interruptible(buf, event, None)
353 })
354 }
355}
356
357impl Deref for SyncDevice {
358 type Target = DeviceImpl;
359 fn deref(&self) -> &Self::Target {
360 &self.0
361 }
362}
363
364#[cfg(unix)]
365impl FromRawFd for SyncDevice {
366 unsafe fn from_raw_fd(fd: RawFd) -> Self {
367 SyncDevice::from_fd(fd).unwrap()
368 }
369}
370#[cfg(unix)]
371impl AsRawFd for SyncDevice {
372 fn as_raw_fd(&self) -> RawFd {
373 self.0.as_raw_fd()
374 }
375}
376#[cfg(unix)]
377impl AsFd for SyncDevice {
378 fn as_fd(&self) -> BorrowedFd<'_> {
379 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
380 }
381}
382#[cfg(unix)]
383impl IntoRawFd for SyncDevice {
384 fn into_raw_fd(self) -> RawFd {
385 self.0.into_raw_fd()
386 }
387}
388
389#[cfg(unix)]
390pub struct BorrowedSyncDevice<'dev> {
391 dev: SyncDevice,
392 _phantom: std::marker::PhantomData<&'dev SyncDevice>,
393}
394#[cfg(unix)]
395impl Deref for BorrowedSyncDevice<'_> {
396 type Target = SyncDevice;
397 fn deref(&self) -> &Self::Target {
398 &self.dev
399 }
400}
401#[cfg(unix)]
402impl BorrowedSyncDevice<'_> {
403 pub unsafe fn borrow_raw(fd: RawFd) -> std::io::Result<Self> {
409 #[allow(unused_unsafe)]
410 unsafe {
411 Ok(Self {
412 dev: SyncDevice::borrow_raw(fd)?,
413 _phantom: std::marker::PhantomData,
414 })
415 }
416 }
417}