mod.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #![allow(unsafe_code)]
  2. use std::{mem, ptr, io};
  3. use std::os::unix::io::RawFd;
  4. use crate::time::Duration;
  5. #[cfg(any(target_os = "linux", target_os = "android"))]
  6. #[path = "linux.rs"]
  7. mod imp;
  8. #[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))]
  9. pub mod raw_socket;
  10. #[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
  11. pub mod bpf;
  12. #[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
  13. pub mod tap_interface;
  14. #[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))]
  15. pub use self::raw_socket::RawSocketDesc;
  16. #[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
  17. pub use self::bpf::BpfDevice as RawSocketDesc;
  18. #[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))]
  19. pub use self::tap_interface::TapInterfaceDesc;
  20. /// Wait until given file descriptor becomes readable, but no longer than given timeout.
  21. pub fn wait(fd: RawFd, duration: Option<Duration>) -> io::Result<()> {
  22. unsafe {
  23. let mut readfds = {
  24. let mut readfds = mem::MaybeUninit::<libc::fd_set>::uninit();
  25. libc::FD_ZERO(readfds.as_mut_ptr());
  26. libc::FD_SET(fd, readfds.as_mut_ptr());
  27. readfds.assume_init()
  28. };
  29. let mut writefds = {
  30. let mut writefds = mem::MaybeUninit::<libc::fd_set>::uninit();
  31. libc::FD_ZERO(writefds.as_mut_ptr());
  32. writefds.assume_init()
  33. };
  34. let mut exceptfds = {
  35. let mut exceptfds = mem::MaybeUninit::<libc::fd_set>::uninit();
  36. libc::FD_ZERO(exceptfds.as_mut_ptr());
  37. exceptfds.assume_init()
  38. };
  39. let mut timeout = libc::timeval { tv_sec: 0, tv_usec: 0 };
  40. let timeout_ptr =
  41. if let Some(duration) = duration {
  42. timeout.tv_sec = duration.secs() as libc::time_t;
  43. timeout.tv_usec = (duration.millis() * 1_000) as libc::suseconds_t;
  44. &mut timeout as *mut _
  45. } else {
  46. ptr::null_mut()
  47. };
  48. let res = libc::select(fd + 1, &mut readfds, &mut writefds, &mut exceptfds, timeout_ptr);
  49. if res == -1 { return Err(io::Error::last_os_error()) }
  50. Ok(())
  51. }
  52. }
  53. #[cfg(all(any(feature = "phy-tap_interface", feature = "phy-raw_socket"), unix))]
  54. #[repr(C)]
  55. #[derive(Debug)]
  56. struct ifreq {
  57. ifr_name: [libc::c_char; libc::IF_NAMESIZE],
  58. ifr_data: libc::c_int /* ifr_ifindex or ifr_mtu */
  59. }
  60. #[cfg(all(any(feature = "phy-tap_interface", feature = "phy-raw_socket"), unix))]
  61. fn ifreq_for(name: &str) -> ifreq {
  62. let mut ifreq = ifreq {
  63. ifr_name: [0; libc::IF_NAMESIZE],
  64. ifr_data: 0
  65. };
  66. for (i, byte) in name.as_bytes().iter().enumerate() {
  67. ifreq.ifr_name[i] = *byte as libc::c_char
  68. }
  69. ifreq
  70. }
  71. #[cfg(all(any(target_os = "linux", target_os = "android"),
  72. any(feature = "phy-tap_interface", feature = "phy-raw_socket")))]
  73. fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq,
  74. cmd: libc::c_ulong) -> io::Result<libc::c_int> {
  75. unsafe {
  76. let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq);
  77. if res == -1 { return Err(io::Error::last_os_error()) }
  78. }
  79. Ok(ifreq.ifr_data)
  80. }