summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/libc/net
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/rustix/src/backend/libc/net
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/src/backend/libc/net')
-rw-r--r--vendor/rustix/src/backend/libc/net/addr.rs10
-rw-r--r--vendor/rustix/src/backend/libc/net/ext.rs8
-rw-r--r--vendor/rustix/src/backend/libc/net/mod.rs10
-rw-r--r--vendor/rustix/src/backend/libc/net/msghdr.rs2
-rw-r--r--vendor/rustix/src/backend/libc/net/read_sockaddr.rs71
-rw-r--r--vendor/rustix/src/backend/libc/net/send_recv.rs16
-rw-r--r--vendor/rustix/src/backend/libc/net/sockopt.rs1065
-rw-r--r--vendor/rustix/src/backend/libc/net/syscalls.rs700
-rw-r--r--vendor/rustix/src/backend/libc/net/write_sockaddr.rs15
9 files changed, 1224 insertions, 673 deletions
diff --git a/vendor/rustix/src/backend/libc/net/addr.rs b/vendor/rustix/src/backend/libc/net/addr.rs
index 6a140d767..719a549b1 100644
--- a/vendor/rustix/src/backend/libc/net/addr.rs
+++ b/vendor/rustix/src/backend/libc/net/addr.rs
@@ -78,6 +78,8 @@ impl SocketAddrUnix {
c::sockaddr_un {
#[cfg(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
sun_len: 0,
+ #[cfg(target_os = "vita")]
+ ss_len: 0,
sun_family: c::AF_UNIX as _,
#[cfg(any(bsd, target_os = "nto"))]
sun_path: [0; 104],
@@ -210,12 +212,15 @@ pub(crate) fn offsetof_sun_path() -> usize {
let z = c::sockaddr_un {
#[cfg(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
sun_len: 0_u8,
+ #[cfg(target_os = "vita")]
+ ss_len: 0,
#[cfg(any(
bsd,
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
))]
sun_family: 0_u8,
#[cfg(not(any(
@@ -223,7 +228,8 @@ pub(crate) fn offsetof_sun_path() -> usize {
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
)))]
sun_family: 0_u16,
#[cfg(any(bsd, target_os = "nto"))]
diff --git a/vendor/rustix/src/backend/libc/net/ext.rs b/vendor/rustix/src/backend/libc/net/ext.rs
index eb7c20d7d..2e11c051d 100644
--- a/vendor/rustix/src/backend/libc/net/ext.rs
+++ b/vendor/rustix/src/backend/libc/net/ext.rs
@@ -83,7 +83,8 @@ pub(crate) const fn sockaddr_in6_new(
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
))]
sin6_len: u8,
sin6_family: c::sa_family_t,
@@ -98,7 +99,8 @@ pub(crate) const fn sockaddr_in6_new(
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
))]
sin6_len,
sin6_family,
@@ -108,6 +110,8 @@ pub(crate) const fn sockaddr_in6_new(
sin6_scope_id,
#[cfg(solarish)]
__sin6_src_id: 0,
+ #[cfg(target_os = "vita")]
+ sin6_vport: 0,
}
}
diff --git a/vendor/rustix/src/backend/libc/net/mod.rs b/vendor/rustix/src/backend/libc/net/mod.rs
index 65c7d0654..d7ab68d52 100644
--- a/vendor/rustix/src/backend/libc/net/mod.rs
+++ b/vendor/rustix/src/backend/libc/net/mod.rs
@@ -1,8 +1,16 @@
pub(crate) mod addr;
pub(crate) mod ext;
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
pub(crate) mod msghdr;
pub(crate) mod read_sockaddr;
pub(crate) mod send_recv;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) mod sockopt;
pub(crate) mod syscalls;
pub(crate) mod write_sockaddr;
diff --git a/vendor/rustix/src/backend/libc/net/msghdr.rs b/vendor/rustix/src/backend/libc/net/msghdr.rs
index 2ccd7f20c..dd9b156a5 100644
--- a/vendor/rustix/src/backend/libc/net/msghdr.rs
+++ b/vendor/rustix/src/backend/libc/net/msghdr.rs
@@ -114,7 +114,7 @@ pub(crate) fn with_unix_msghdr<R>(
) -> R {
f({
let mut h = zero_msghdr();
- h.msg_name = as_ptr(addr) as _;
+ h.msg_name = as_ptr(&addr.unix) as _;
h.msg_namelen = addr.addr_len();
h.msg_iov = iov.as_ptr() as _;
h.msg_iovlen = msg_iov_len(iov.len());
diff --git a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs b/vendor/rustix/src/backend/libc/net/read_sockaddr.rs
index 604f24928..6da7a50dd 100644
--- a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs
+++ b/vendor/rustix/src/backend/libc/net/read_sockaddr.rs
@@ -1,5 +1,5 @@
-//! The BSD sockets API requires us to read the `ss_family` field before
-//! we can interpret the rest of a `sockaddr` produced by the kernel.
+//! The BSD sockets API requires us to read the `ss_family` field before we can
+//! interpret the rest of a `sockaddr` produced by the kernel.
#[cfg(unix)]
use super::addr::SocketAddrUnix;
@@ -14,14 +14,40 @@ use core::mem::size_of;
// This must match the header of `sockaddr`.
#[repr(C)]
struct sockaddr_header {
- #[cfg(any(bsd, target_os = "haiku"))]
+ #[cfg(any(
+ bsd,
+ target_os = "aix",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "nto",
+ target_os = "vita"
+ ))]
sa_len: u8,
- #[cfg(any(bsd, target_os = "haiku"))]
+ #[cfg(any(
+ bsd,
+ target_os = "aix",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "nto",
+ target_os = "vita"
+ ))]
ss_family: u8,
- #[cfg(not(any(bsd, target_os = "haiku")))]
+ #[cfg(not(any(
+ bsd,
+ target_os = "aix",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "nto",
+ target_os = "vita"
+ )))]
ss_family: u16,
}
+/// Read the `ss_family` field from a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
#[inline]
unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
// Assert that we know the layout of `sockaddr`.
@@ -31,7 +57,8 @@ unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
))]
sa_len: 0_u8,
#[cfg(any(
@@ -39,7 +66,8 @@ unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
))]
sa_family: 0_u8,
#[cfg(not(any(
@@ -47,7 +75,8 @@ unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
)))]
sa_family: 0_u16,
#[cfg(not(target_os = "haiku"))]
@@ -138,10 +167,10 @@ pub(crate) unsafe fn read_sockaddr(
// Otherwise we expect a NUL-terminated filesystem path.
// Trim off unused bytes from the end of `path_bytes`.
- let path_bytes = if cfg!(target_os = "freebsd") {
- // FreeBSD sometimes sets the length to longer than the length
- // of the NUL-terminated string. Find the NUL and truncate the
- // string accordingly.
+ let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) {
+ // FreeBSD and illumos sometimes set the length to longer
+ // than the length of the NUL-terminated string. Find the
+ // NUL and truncate the string accordingly.
&decode.sun_path[..decode
.sun_path
.iter()
@@ -168,6 +197,11 @@ pub(crate) unsafe fn read_sockaddr(
}
}
+/// Read an optional socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
pub(crate) unsafe fn maybe_read_sockaddr_os(
storage: *const c::sockaddr_storage,
len: usize,
@@ -185,6 +219,11 @@ pub(crate) unsafe fn maybe_read_sockaddr_os(
}
}
+/// Read a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
pub(crate) unsafe fn read_sockaddr_os(
storage: *const c::sockaddr_storage,
len: usize,
@@ -250,10 +289,10 @@ unsafe fn inner_read_sockaddr_os(
assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0);
let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];
- // FreeBSD sometimes sets the length to longer than the length
- // of the NUL-terminated string. Find the NUL and truncate the
- // string accordingly.
- #[cfg(target_os = "freebsd")]
+ // FreeBSD and illumos sometimes set the length to longer than
+ // the length of the NUL-terminated string. Find the NUL and
+ // truncate the string accordingly.
+ #[cfg(any(solarish, target_os = "freebsd"))]
let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()];
SocketAddrAny::Unix(
diff --git a/vendor/rustix/src/backend/libc/net/send_recv.rs b/vendor/rustix/src/backend/libc/net/send_recv.rs
index 76dc97e78..5dc60ddcd 100644
--- a/vendor/rustix/src/backend/libc/net/send_recv.rs
+++ b/vendor/rustix/src/backend/libc/net/send_recv.rs
@@ -2,7 +2,8 @@ use crate::backend::c;
use bitflags::bitflags;
bitflags! {
- /// `MSG_* flags for use with [`send`], [`send_to`], and related functions.
+ /// `MSG_*` flags for use with [`send`], [`send_to`], and related
+ /// functions.
///
/// [`send`]: crate::net::send
/// [`sendto`]: crate::net::sendto
@@ -18,6 +19,7 @@ bitflags! {
target_os = "espidf",
target_os = "nto",
target_os = "haiku",
+ target_os = "vita",
)))]
const CONFIRM = bitcast!(c::MSG_CONFIRM);
/// `MSG_DONTROUTE`
@@ -36,21 +38,23 @@ bitflags! {
target_os = "aix",
target_os = "haiku",
target_os = "nto",
+ target_os = "vita",
)))]
const MORE = bitcast!(c::MSG_MORE);
- #[cfg(not(any(apple, windows)))]
+ #[cfg(not(any(apple, windows, target_os = "vita")))]
/// `MSG_NOSIGNAL`
const NOSIGNAL = bitcast!(c::MSG_NOSIGNAL);
/// `MSG_OOB`
const OOB = bitcast!(c::MSG_OOB);
- /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
const _ = !0;
}
}
bitflags! {
- /// `MSG_* flags for use with [`recv`], [`recvfrom`], and related functions.
+ /// `MSG_*` flags for use with [`recv`], [`recvfrom`], and related
+ /// functions.
///
/// [`recv`]: crate::net::recv
/// [`recvfrom`]: crate::net::recvfrom
@@ -65,6 +69,7 @@ bitflags! {
target_os = "espidf",
target_os = "haiku",
target_os = "nto",
+ target_os = "vita",
)))]
/// `MSG_CMSG_CLOEXEC`
const CMSG_CLOEXEC = bitcast!(c::MSG_CMSG_CLOEXEC);
@@ -80,6 +85,7 @@ bitflags! {
target_os = "espidf",
target_os = "haiku",
target_os = "nto",
+ target_os = "vita",
)))]
const ERRQUEUE = bitcast!(c::MSG_ERRQUEUE);
/// `MSG_OOB`
@@ -91,7 +97,7 @@ bitflags! {
/// `MSG_WAITALL`
const WAITALL = bitcast!(c::MSG_WAITALL);
- /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
+ /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
const _ = !0;
}
}
diff --git a/vendor/rustix/src/backend/libc/net/sockopt.rs b/vendor/rustix/src/backend/libc/net/sockopt.rs
new file mode 100644
index 000000000..cff2ca288
--- /dev/null
+++ b/vendor/rustix/src/backend/libc/net/sockopt.rs
@@ -0,0 +1,1065 @@
+//! libc syscalls supporting `rustix::net::sockopt`.
+
+use super::ext::{in6_addr_new, in_addr_new};
+use crate::backend::c;
+use crate::backend::conv::{borrowed_fd, ret};
+use crate::fd::BorrowedFd;
+#[cfg(feature = "alloc")]
+#[cfg(any(
+ linux_like,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos"
+))]
+use crate::ffi::CStr;
+use crate::io;
+use crate::net::sockopt::Timeout;
+#[cfg(not(any(
+ apple,
+ windows,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "vita",
+)))]
+use crate::net::AddressFamily;
+#[cfg(any(
+ linux_kernel,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_env = "newlib"
+))]
+use crate::net::Protocol;
+#[cfg(any(
+ linux_kernel,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_env = "newlib"
+))]
+use crate::net::RawProtocol;
+use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
+#[cfg(any(linux_kernel, target_os = "fuchsia"))]
+use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrV4};
+#[cfg(linux_kernel)]
+use crate::net::{SocketAddrV6, UCred};
+use crate::utils::as_mut_ptr;
+#[cfg(feature = "alloc")]
+#[cfg(any(
+ linux_like,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos"
+))]
+use alloc::borrow::ToOwned;
+#[cfg(feature = "alloc")]
+#[cfg(any(
+ linux_like,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos"
+))]
+use alloc::string::String;
+#[cfg(apple)]
+use c::TCP_KEEPALIVE as TCP_KEEPIDLE;
+#[cfg(not(any(apple, target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+use c::TCP_KEEPIDLE;
+use core::mem::{size_of, MaybeUninit};
+use core::time::Duration;
+#[cfg(windows)]
+use windows_sys::Win32::Foundation::BOOL;
+
+#[inline]
+fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result<T> {
+ let mut optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ let mut value = MaybeUninit::<T>::zeroed();
+ getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?;
+
+ // On Windows at least, `getsockopt` has been observed writing 1
+ // byte on at least (`IPPROTO_TCP`, `TCP_NODELAY`), even though
+ // Windows' documentation says that should write a 4-byte `BOOL`.
+ // So, we initialize the memory to zeros above, and just assert
+ // that `getsockopt` doesn't write too many bytes here.
+ assert!(
+ optlen as usize <= size_of::<T>(),
+ "unexpected getsockopt size"
+ );
+
+ unsafe { Ok(value.assume_init()) }
+}
+
+#[inline]
+fn getsockopt_raw<T>(
+ fd: BorrowedFd<'_>,
+ level: i32,
+ optname: i32,
+ value: &mut MaybeUninit<T>,
+ optlen: &mut c::socklen_t,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::getsockopt(
+ borrowed_fd(fd),
+ level,
+ optname,
+ as_mut_ptr(value).cast(),
+ optlen,
+ ))
+ }
+}
+
+#[inline]
+fn setsockopt<T: Copy>(fd: BorrowedFd<'_>, level: i32, optname: i32, value: T) -> io::Result<()> {
+ let optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+ setsockopt_raw(fd, level, optname, &value, optlen)
+}
+
+#[inline]
+fn setsockopt_raw<T>(
+ fd: BorrowedFd<'_>,
+ level: i32,
+ optname: i32,
+ ptr: *const T,
+ optlen: c::socklen_t,
+) -> io::Result<()> {
+ unsafe {
+ ret(c::setsockopt(
+ borrowed_fd(fd),
+ level,
+ optname,
+ ptr.cast(),
+ optlen,
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result<SocketType> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_TYPE)
+}
+
+#[inline]
+pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_REUSEADDR, from_bool(reuseaddr))
+}
+
+#[inline]
+pub(crate) fn get_socket_reuseaddr(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_REUSEADDR).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_BROADCAST, from_bool(broadcast))
+}
+
+#[inline]
+pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_BROADCAST).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_socket_linger(fd: BorrowedFd<'_>, linger: Option<Duration>) -> io::Result<()> {
+ // Convert `linger` to seconds, rounding up.
+ let l_linger = if let Some(linger) = linger {
+ duration_to_secs(linger)?
+ } else {
+ 0
+ };
+ let linger = c::linger {
+ l_onoff: linger.is_some().into(),
+ l_linger,
+ };
+ setsockopt(fd, c::SOL_SOCKET, c::SO_LINGER, linger)
+}
+
+#[inline]
+pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result<Option<Duration>> {
+ let linger: c::linger = getsockopt(fd, c::SOL_SOCKET, c::SO_LINGER)?;
+ Ok((linger.l_onoff != 0).then(|| Duration::from_secs(linger.l_linger as u64)))
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_PASSCRED, from_bool(passcred))
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_PASSCRED).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+) -> io::Result<()> {
+ let optname = match id {
+ Timeout::Recv => c::SO_RCVTIMEO,
+ Timeout::Send => c::SO_SNDTIMEO,
+ };
+
+ #[cfg(not(windows))]
+ let timeout = match timeout {
+ Some(timeout) => {
+ if timeout == Duration::ZERO {
+ return Err(io::Errno::INVAL);
+ }
+
+ // Rust's musl libc bindings deprecated `time_t` while they
+ // transition to 64-bit `time_t`. What we want here is just
+ // “whatever type `timeval`'s `tv_sec` is”, so we're ok using
+ // the deprecated type.
+ #[allow(deprecated)]
+ let tv_sec = timeout.as_secs().try_into().unwrap_or(c::time_t::MAX);
+
+ // `subsec_micros` rounds down, so we use `subsec_nanos` and
+ // manually round up.
+ let mut timeout = c::timeval {
+ tv_sec,
+ tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _,
+ };
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ timeout.tv_usec = 1;
+ }
+ timeout
+ }
+ None => c::timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ },
+ };
+
+ #[cfg(windows)]
+ let timeout: u32 = match timeout {
+ Some(timeout) => {
+ if timeout == Duration::ZERO {
+ return Err(io::Errno::INVAL);
+ }
+
+ // `as_millis` rounds down, so we use `as_nanos` and
+ // manually round up.
+ let mut timeout: u32 = ((timeout.as_nanos() + 999_999) / 1_000_000)
+ .try_into()
+ .map_err(|_convert_err| io::Errno::INVAL)?;
+ if timeout == 0 {
+ timeout = 1;
+ }
+ timeout
+ }
+ None => 0,
+ };
+
+ setsockopt(fd, c::SOL_SOCKET, optname, timeout)
+}
+
+#[inline]
+pub(crate) fn get_socket_timeout(fd: BorrowedFd<'_>, id: Timeout) -> io::Result<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => c::SO_RCVTIMEO,
+ Timeout::Send => c::SO_SNDTIMEO,
+ };
+
+ #[cfg(not(windows))]
+ {
+ let timeout: c::timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ Ok(None)
+ } else {
+ Ok(Some(
+ Duration::from_secs(timeout.tv_sec as u64)
+ + Duration::from_micros(timeout.tv_usec as u64),
+ ))
+ }
+ }
+
+ #[cfg(windows)]
+ {
+ let timeout: u32 = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ if timeout == 0 {
+ Ok(None)
+ } else {
+ Ok(Some(Duration::from_millis(timeout as u64)))
+ }
+ }
+}
+
+#[cfg(any(apple, freebsdlike, target_os = "netbsd"))]
+#[inline]
+pub(crate) fn get_socket_nosigpipe(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE).map(to_bool)
+}
+
+#[cfg(any(apple, freebsdlike, target_os = "netbsd"))]
+#[inline]
+pub(crate) fn set_socket_nosigpipe(fd: BorrowedFd<'_>, val: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE, from_bool(val))
+}
+
+#[inline]
+pub(crate) fn get_socket_error(fd: BorrowedFd<'_>) -> io::Result<Result<(), io::Errno>> {
+ let err: c::c_int = getsockopt(fd, c::SOL_SOCKET, c::SO_ERROR)?;
+ Ok(if err == 0 {
+ Ok(())
+ } else {
+ Err(io::Errno::from_raw_os_error(err))
+ })
+}
+
+#[inline]
+pub(crate) fn set_socket_keepalive(fd: BorrowedFd<'_>, keepalive: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_KEEPALIVE, from_bool(keepalive))
+}
+
+#[inline]
+pub(crate) fn get_socket_keepalive(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_KEEPALIVE).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_socket_recv_buffer_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
+ let size: c::c_int = size.try_into().map_err(|_| io::Errno::INVAL)?;
+ setsockopt(fd, c::SOL_SOCKET, c::SO_RCVBUF, size)
+}
+
+#[inline]
+pub(crate) fn get_socket_recv_buffer_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_RCVBUF).map(|size: u32| size as usize)
+}
+
+#[inline]
+pub(crate) fn set_socket_send_buffer_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
+ let size: c::c_int = size.try_into().map_err(|_| io::Errno::INVAL)?;
+ setsockopt(fd, c::SOL_SOCKET, c::SO_SNDBUF, size)
+}
+
+#[inline]
+pub(crate) fn get_socket_send_buffer_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_SNDBUF).map(|size: u32| size as usize)
+}
+
+#[inline]
+#[cfg(not(any(
+ apple,
+ windows,
+ target_os = "aix",
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "nto",
+ target_os = "vita",
+)))]
+pub(crate) fn get_socket_domain(fd: BorrowedFd<'_>) -> io::Result<AddressFamily> {
+ let domain: c::c_int = getsockopt(fd, c::SOL_SOCKET, c::SO_DOMAIN)?;
+ Ok(AddressFamily(
+ domain.try_into().map_err(|_| io::Errno::OPNOTSUPP)?,
+ ))
+}
+
+#[inline]
+#[cfg(not(apple))] // Apple platforms declare the constant, but do not actually implement it.
+pub(crate) fn get_socket_acceptconn(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_ACCEPTCONN).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_socket_oobinline(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_OOBINLINE, from_bool(value))
+}
+
+#[inline]
+pub(crate) fn get_socket_oobinline(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_OOBINLINE).map(to_bool)
+}
+
+#[cfg(not(any(solarish, windows)))]
+#[inline]
+pub(crate) fn set_socket_reuseport(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_REUSEPORT, from_bool(value))
+}
+
+#[cfg(not(any(solarish, windows)))]
+#[inline]
+pub(crate) fn get_socket_reuseport(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_REUSEPORT).map(to_bool)
+}
+
+#[cfg(target_os = "freebsd")]
+#[inline]
+pub(crate) fn set_socket_reuseport_lb(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_REUSEPORT_LB, from_bool(value))
+}
+
+#[cfg(target_os = "freebsd")]
+#[inline]
+pub(crate) fn get_socket_reuseport_lb(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_REUSEPORT_LB).map(to_bool)
+}
+
+#[cfg(any(
+ linux_kernel,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_env = "newlib"
+))]
+#[inline]
+pub(crate) fn get_socket_protocol(fd: BorrowedFd<'_>) -> io::Result<Option<Protocol>> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_PROTOCOL)
+ .map(|raw| RawProtocol::new(raw).map(Protocol::from_raw))
+}
+
+#[cfg(target_os = "linux")]
+#[inline]
+pub(crate) fn get_socket_cookie(fd: BorrowedFd<'_>) -> io::Result<u64> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_COOKIE)
+}
+
+#[cfg(target_os = "linux")]
+#[inline]
+pub(crate) fn get_socket_incoming_cpu(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_INCOMING_CPU)
+}
+
+#[cfg(target_os = "linux")]
+#[inline]
+pub(crate) fn set_socket_incoming_cpu(fd: BorrowedFd<'_>, value: u32) -> io::Result<()> {
+ setsockopt(fd, c::SOL_SOCKET, c::SO_INCOMING_CPU, value)
+}
+
+#[inline]
+pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IP_TTL, ttl)
+}
+
+#[inline]
+pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP, c::IP_TTL)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_V6ONLY, from_bool(only_v6))
+}
+
+#[inline]
+pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_V6ONLY).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_ip_multicast_loop(fd: BorrowedFd<'_>, multicast_loop: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IP,
+ c::IP_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+}
+
+#[inline]
+pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP, c::IP_MULTICAST_LOOP).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IP_MULTICAST_TTL, multicast_ttl)
+}
+
+#[inline]
+pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP, c::IP_MULTICAST_TTL)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_multicast_loop(fd: BorrowedFd<'_>, multicast_loop: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IPV6,
+ c::IPV6_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+}
+
+#[inline]
+pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP).map(to_bool)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_multicast_hops(fd: BorrowedFd<'_>, multicast_hops: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IPV6_MULTICAST_HOPS, multicast_hops)
+}
+
+#[inline]
+pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP, c::IPV6_MULTICAST_HOPS)
+}
+
+#[inline]
+pub(crate) fn set_ip_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+) -> io::Result<()> {
+ let mreq = to_ip_mreq(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
+}
+
+#[cfg(any(
+ apple,
+ freebsdlike,
+ linux_like,
+ target_os = "fuchsia",
+ target_os = "openbsd"
+))]
+#[inline]
+pub(crate) fn set_ip_add_membership_with_ifindex(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ address: &Ipv4Addr,
+ ifindex: i32,
+) -> io::Result<()> {
+ let mreqn = to_ip_mreqn(multiaddr, address, ifindex);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreqn)
+}
+
+#[cfg(any(apple, freebsdlike, linux_like, solarish, target_os = "aix"))]
+#[inline]
+pub(crate) fn set_ip_add_source_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ sourceaddr: &Ipv4Addr,
+) -> io::Result<()> {
+ let mreq_source = to_imr_source(multiaddr, interface, sourceaddr);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_ADD_SOURCE_MEMBERSHIP, mreq_source)
+}
+
+#[cfg(any(apple, freebsdlike, linux_like, solarish, target_os = "aix"))]
+#[inline]
+pub(crate) fn set_ip_drop_source_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ sourceaddr: &Ipv4Addr,
+) -> io::Result<()> {
+ let mreq_source = to_imr_source(multiaddr, interface, sourceaddr);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_DROP_SOURCE_MEMBERSHIP, mreq_source)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_add_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+) -> io::Result<()> {
+ #[cfg(not(any(
+ bsd,
+ solarish,
+ target_os = "haiku",
+ target_os = "l4re",
+ target_os = "nto"
+ )))]
+ use c::IPV6_ADD_MEMBERSHIP;
+ #[cfg(any(
+ bsd,
+ solarish,
+ target_os = "haiku",
+ target_os = "l4re",
+ target_os = "nto"
+ ))]
+ use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
+
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
+}
+
+#[inline]
+pub(crate) fn set_ip_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+) -> io::Result<()> {
+ let mreq = to_ip_mreq(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
+}
+
+#[cfg(any(
+ apple,
+ freebsdlike,
+ linux_like,
+ target_os = "fuchsia",
+ target_os = "openbsd"
+))]
+#[inline]
+pub(crate) fn set_ip_drop_membership_with_ifindex(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv4Addr,
+ address: &Ipv4Addr,
+ ifindex: i32,
+) -> io::Result<()> {
+ let mreqn = to_ip_mreqn(multiaddr, address, ifindex);
+ setsockopt(fd, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreqn)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_drop_membership(
+ fd: BorrowedFd<'_>,
+ multiaddr: &Ipv6Addr,
+ interface: u32,
+) -> io::Result<()> {
+ #[cfg(not(any(
+ bsd,
+ solarish,
+ target_os = "haiku",
+ target_os = "l4re",
+ target_os = "nto"
+ )))]
+ use c::IPV6_DROP_MEMBERSHIP;
+ #[cfg(any(
+ bsd,
+ solarish,
+ target_os = "haiku",
+ target_os = "l4re",
+ target_os = "nto"
+ ))]
+ use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+
+ let mreq = to_ipv6mr(multiaddr, interface);
+ setsockopt(fd, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
+}
+
+#[inline]
+pub(crate) fn get_ipv6_unicast_hops(fd: BorrowedFd<'_>) -> io::Result<u8> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS).map(|hops: c::c_int| hops as u8)
+}
+
+#[inline]
+pub(crate) fn set_ipv6_unicast_hops(fd: BorrowedFd<'_>, hops: Option<u8>) -> io::Result<()> {
+ let hops = match hops {
+ Some(hops) => hops as c::c_int,
+ None => -1,
+ };
+ setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, hops)
+}
+
+#[cfg(any(
+ bsd,
+ linux_like,
+ target_os = "aix",
+ target_os = "fuchsia",
+ target_os = "haiku",
+ target_os = "nto",
+ target_env = "newlib"
+))]
+#[inline]
+pub(crate) fn set_ip_tos(fd: BorrowedFd<'_>, value: u8) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IP_TOS, i32::from(value))
+}
+
+#[cfg(any(
+ bsd,
+ linux_like,
+ target_os = "aix",
+ target_os = "fuchsia",
+ target_os = "haiku",
+ target_os = "nto",
+ target_env = "newlib"
+))]
+#[inline]
+pub(crate) fn get_ip_tos(fd: BorrowedFd<'_>) -> io::Result<u8> {
+ let value: i32 = getsockopt(fd, c::IPPROTO_IP, c::IP_TOS)?;
+ Ok(value as u8)
+}
+
+#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn set_ip_recvtos(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IP_RECVTOS, from_bool(value))
+}
+
+#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_ip_recvtos(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP, c::IP_RECVTOS).map(to_bool)
+}
+
+#[cfg(any(
+ bsd,
+ linux_like,
+ target_os = "aix",
+ target_os = "fuchsia",
+ target_os = "nto"
+))]
+#[inline]
+pub(crate) fn set_ipv6_recvtclass(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_RECVTCLASS, from_bool(value))
+}
+
+#[cfg(any(
+ bsd,
+ linux_like,
+ target_os = "aix",
+ target_os = "fuchsia",
+ target_os = "nto"
+))]
+#[inline]
+pub(crate) fn get_ipv6_recvtclass(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_RECVTCLASS).map(to_bool)
+}
+
+#[cfg(any(linux_kernel, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn set_ip_freebind(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP, c::IP_FREEBIND, from_bool(value))
+}
+
+#[cfg(any(linux_kernel, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_ip_freebind(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP, c::IP_FREEBIND).map(to_bool)
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn set_ipv6_freebind(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_FREEBIND, from_bool(value))
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn get_ipv6_freebind(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_FREEBIND).map(to_bool)
+}
+
+#[cfg(any(linux_kernel, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_ip_original_dst(fd: BorrowedFd<'_>) -> io::Result<SocketAddrV4> {
+ let level = c::IPPROTO_IP;
+ let optname = c::SO_ORIGINAL_DST;
+ let mut value = MaybeUninit::<SocketAddrStorage>::uninit();
+ let mut optlen = core::mem::size_of_val(&value).try_into().unwrap();
+
+ getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?;
+
+ let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? };
+ match any {
+ SocketAddrAny::V4(v4) => Ok(v4),
+ _ => unreachable!(),
+ }
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn get_ipv6_original_dst(fd: BorrowedFd<'_>) -> io::Result<SocketAddrV6> {
+ let level = c::IPPROTO_IPV6;
+ let optname = c::IP6T_SO_ORIGINAL_DST;
+ let mut value = MaybeUninit::<SocketAddrStorage>::uninit();
+ let mut optlen = core::mem::size_of_val(&value).try_into().unwrap();
+
+ getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?;
+
+ let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? };
+ match any {
+ SocketAddrAny::V6(v6) => Ok(v6),
+ _ => unreachable!(),
+ }
+}
+
+#[cfg(not(any(
+ solarish,
+ windows,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "vita"
+)))]
+#[inline]
+pub(crate) fn set_ipv6_tclass(fd: BorrowedFd<'_>, value: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_TCLASS, value)
+}
+
+#[cfg(not(any(
+ solarish,
+ windows,
+ target_os = "espidf",
+ target_os = "haiku",
+ target_os = "vita"
+)))]
+#[inline]
+pub(crate) fn get_ipv6_tclass(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_TCLASS)
+}
+
+#[inline]
+pub(crate) fn set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_NODELAY, from_bool(nodelay))
+}
+
+#[inline]
+pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_NODELAY).map(to_bool)
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn set_tcp_keepcnt(fd: BorrowedFd<'_>, count: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPCNT, count)
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn get_tcp_keepcnt(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPCNT)
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn set_tcp_keepidle(fd: BorrowedFd<'_>, duration: Duration) -> io::Result<()> {
+ let secs: c::c_uint = duration_to_secs(duration)?;
+ setsockopt(fd, c::IPPROTO_TCP, TCP_KEEPIDLE, secs)
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn get_tcp_keepidle(fd: BorrowedFd<'_>) -> io::Result<Duration> {
+ let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP, TCP_KEEPIDLE)?;
+ Ok(Duration::from_secs(secs as u64))
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn set_tcp_keepintvl(fd: BorrowedFd<'_>, duration: Duration) -> io::Result<()> {
+ let secs: c::c_uint = duration_to_secs(duration)?;
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPINTVL, secs)
+}
+
+#[inline]
+#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
+pub(crate) fn get_tcp_keepintvl(fd: BorrowedFd<'_>) -> io::Result<Duration> {
+ let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPINTVL)?;
+ Ok(Duration::from_secs(secs as u64))
+}
+
+#[inline]
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+pub(crate) fn set_tcp_user_timeout(fd: BorrowedFd<'_>, value: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_USER_TIMEOUT, value)
+}
+
+#[inline]
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+pub(crate) fn get_tcp_user_timeout(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_USER_TIMEOUT)
+}
+
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn set_tcp_quickack(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_QUICKACK, from_bool(value))
+}
+
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_tcp_quickack(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_QUICKACK).map(to_bool)
+}
+
+#[cfg(any(
+ linux_like,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos"
+))]
+#[inline]
+pub(crate) fn set_tcp_congestion(fd: BorrowedFd<'_>, value: &str) -> io::Result<()> {
+ let level = c::IPPROTO_TCP;
+ let optname = c::TCP_CONGESTION;
+ let optlen = value.len().try_into().unwrap();
+ setsockopt_raw(fd, level, optname, value.as_ptr(), optlen)
+}
+
+#[cfg(feature = "alloc")]
+#[cfg(any(
+ linux_like,
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos"
+))]
+#[inline]
+pub(crate) fn get_tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
+ let level = c::IPPROTO_TCP;
+ let optname = c::TCP_CONGESTION;
+ const OPTLEN: c::socklen_t = 16;
+ let mut value = MaybeUninit::<[MaybeUninit<u8>; OPTLEN as usize]>::uninit();
+ let mut optlen = OPTLEN;
+ getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?;
+ unsafe {
+ let value = value.assume_init();
+ let slice: &[u8] = core::mem::transmute(&value[..optlen as usize]);
+ assert!(slice.iter().any(|b| *b == b'\0'));
+ Ok(
+ core::str::from_utf8(CStr::from_ptr(slice.as_ptr().cast()).to_bytes())
+ .unwrap()
+ .to_owned(),
+ )
+ }
+}
+
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn set_tcp_thin_linear_timeouts(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_TCP,
+ c::TCP_THIN_LINEAR_TIMEOUTS,
+ from_bool(value),
+ )
+}
+
+#[cfg(any(linux_like, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_tcp_thin_linear_timeouts(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_THIN_LINEAR_TIMEOUTS).map(to_bool)
+}
+
+#[cfg(any(linux_like, solarish, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn set_tcp_cork(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP, c::TCP_CORK, from_bool(value))
+}
+
+#[cfg(any(linux_like, solarish, target_os = "fuchsia"))]
+#[inline]
+pub(crate) fn get_tcp_cork(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP, c::TCP_CORK).map(to_bool)
+}
+
+#[cfg(linux_kernel)]
+#[inline]
+pub(crate) fn get_socket_peercred(fd: BorrowedFd<'_>) -> io::Result<UCred> {
+ getsockopt(fd, c::SOL_SOCKET, c::SO_PEERCRED)
+}
+
+#[inline]
+fn to_ip_mreq(multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> c::ip_mreq {
+ c::ip_mreq {
+ imr_multiaddr: to_imr_addr(multiaddr),
+ imr_interface: to_imr_addr(interface),
+ }
+}
+
+#[cfg(any(
+ apple,
+ freebsdlike,
+ linux_like,
+ target_os = "fuchsia",
+ target_os = "openbsd"
+))]
+#[inline]
+fn to_ip_mreqn(multiaddr: &Ipv4Addr, address: &Ipv4Addr, ifindex: i32) -> c::ip_mreqn {
+ c::ip_mreqn {
+ imr_multiaddr: to_imr_addr(multiaddr),
+ imr_address: to_imr_addr(address),
+ imr_ifindex: ifindex,
+ }
+}
+
+#[cfg(any(apple, freebsdlike, linux_like, solarish, target_os = "aix"))]
+#[inline]
+fn to_imr_source(
+ multiaddr: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ sourceaddr: &Ipv4Addr,
+) -> c::ip_mreq_source {
+ c::ip_mreq_source {
+ imr_multiaddr: to_imr_addr(multiaddr),
+ imr_interface: to_imr_addr(interface),
+ imr_sourceaddr: to_imr_addr(sourceaddr),
+ }
+}
+
+#[inline]
+fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr {
+ in_addr_new(u32::from_ne_bytes(addr.octets()))
+}
+
+#[inline]
+fn to_ipv6mr(multiaddr: &Ipv6Addr, interface: u32) -> c::ipv6_mreq {
+ c::ipv6_mreq {
+ ipv6mr_multiaddr: to_ipv6mr_multiaddr(multiaddr),
+ ipv6mr_interface: to_ipv6mr_interface(interface),
+ }
+}
+
+#[inline]
+fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr {
+ in6_addr_new(multiaddr.octets())
+}
+
+#[cfg(target_os = "android")]
+#[inline]
+fn to_ipv6mr_interface(interface: u32) -> c::c_int {
+ interface as c::c_int
+}
+
+#[cfg(not(target_os = "android"))]
+#[inline]
+fn to_ipv6mr_interface(interface: u32) -> c::c_uint {
+ interface as c::c_uint
+}
+
+// `getsockopt` and `setsockopt` represent boolean values as integers.
+#[cfg(not(windows))]
+type RawSocketBool = c::c_int;
+#[cfg(windows)]
+type RawSocketBool = BOOL;
+
+// Wrap `RawSocketBool` in a newtype to discourage misuse.
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+struct SocketBool(RawSocketBool);
+
+// Convert from a `bool` to a `SocketBool`.
+#[inline]
+fn from_bool(value: bool) -> SocketBool {
+ SocketBool(value.into())
+}
+
+// Convert from a `SocketBool` to a `bool`.
+#[inline]
+fn to_bool(value: SocketBool) -> bool {
+ value.0 != 0
+}
+
+/// Convert to seconds, rounding up if necessary.
+#[inline]
+fn duration_to_secs<T: TryFrom<u64>>(duration: Duration) -> io::Result<T> {
+ let mut secs = duration.as_secs();
+ if duration.subsec_nanos() != 0 {
+ secs = secs.checked_add(1).ok_or(io::Errno::INVAL)?;
+ }
+ T::try_from(secs).map_err(|_e| io::Errno::INVAL)
+}
diff --git a/vendor/rustix/src/backend/libc/net/syscalls.rs b/vendor/rustix/src/backend/libc/net/syscalls.rs
index 2e968ba3e..97b862033 100644
--- a/vendor/rustix/src/backend/libc/net/syscalls.rs
+++ b/vendor/rustix/src/backend/libc/net/syscalls.rs
@@ -2,7 +2,6 @@
#[cfg(unix)]
use super::addr::SocketAddrUnix;
-use super::ext::{in6_addr_new, in_addr_new};
use crate::backend::c;
use crate::backend::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len};
use crate::fd::{BorrowedFd, OwnedFd};
@@ -10,7 +9,13 @@ use crate::io;
use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
use crate::utils::as_ptr;
use core::mem::{size_of, MaybeUninit};
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
use {
super::msghdr::{with_noaddr_msghdr, with_recv_msghdr, with_v4_msghdr, with_v6_msghdr},
crate::io::{IoSlice, IoSliceMut},
@@ -244,6 +249,19 @@ pub(crate) fn connect_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io:
}
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+pub(crate) fn connect_unspec(sockfd: BorrowedFd<'_>) -> io::Result<()> {
+ debug_assert_eq!(c::AF_UNSPEC, 0);
+ let addr = MaybeUninit::<c::sockaddr_storage>::zeroed();
+ unsafe {
+ ret(c::connect(
+ borrowed_fd(sockfd),
+ as_ptr(&addr).cast(),
+ size_of::<c::sockaddr_storage>() as c::socklen_t,
+ ))
+ }
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
pub(crate) fn listen(sockfd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
unsafe { ret(c::listen(borrowed_fd(sockfd), backlog)) }
}
@@ -256,7 +274,13 @@ pub(crate) fn accept(sockfd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
}
}
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
pub(crate) fn recvmsg(
sockfd: BorrowedFd<'_>,
iov: &mut [IoSliceMut<'_>],
@@ -288,7 +312,13 @@ pub(crate) fn recvmsg(
})
}
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
pub(crate) fn sendmsg(
sockfd: BorrowedFd<'_>,
iov: &[IoSlice<'_>],
@@ -304,7 +334,13 @@ pub(crate) fn sendmsg(
})
}
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
pub(crate) fn sendmsg_v4(
sockfd: BorrowedFd<'_>,
addr: &SocketAddrV4,
@@ -321,7 +357,13 @@ pub(crate) fn sendmsg_v4(
})
}
-#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")))]
+#[cfg(not(any(
+ windows,
+ target_os = "espidf",
+ target_os = "redox",
+ target_os = "vita",
+ target_os = "wasi"
+)))]
pub(crate) fn sendmsg_v6(
sockfd: BorrowedFd<'_>,
addr: &SocketAddrV6,
@@ -338,7 +380,10 @@ pub(crate) fn sendmsg_v6(
})
}
-#[cfg(all(unix, not(any(target_os = "espidf", target_os = "redox"))))]
+#[cfg(all(
+ unix,
+ not(any(target_os = "espidf", target_os = "redox", target_os = "vita"))
+))]
pub(crate) fn sendmsg_unix(
sockfd: BorrowedFd<'_>,
addr: &SocketAddrUnix,
@@ -363,6 +408,7 @@ pub(crate) fn sendmsg_unix(
target_os = "haiku",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
target_os = "wasi",
)))]
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
@@ -402,6 +448,7 @@ pub(crate) fn acceptfrom(sockfd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<
target_os = "haiku",
target_os = "nto",
target_os = "redox",
+ target_os = "vita",
target_os = "wasi",
)))]
pub(crate) fn acceptfrom_with(
@@ -432,7 +479,8 @@ pub(crate) fn acceptfrom_with(
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita",
))]
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, _flags: SocketFlags) -> io::Result<OwnedFd> {
accept(sockfd)
@@ -446,7 +494,8 @@ pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, _flags: SocketFlags) -> io::Re
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita",
))]
pub(crate) fn acceptfrom_with(
sockfd: BorrowedFd<'_>,
@@ -515,636 +564,3 @@ pub(crate) fn socketpair(
Ok((fd0, fd1))
}
}
-
-#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
-pub(crate) mod sockopt {
- use super::{c, in6_addr_new, in_addr_new, BorrowedFd};
- use crate::io;
- use crate::net::sockopt::Timeout;
- #[cfg(not(any(
- apple,
- windows,
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "espidf",
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "nto",
- )))]
- use crate::net::AddressFamily;
- use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
- use crate::utils::as_mut_ptr;
- #[cfg(apple)]
- use c::TCP_KEEPALIVE as TCP_KEEPIDLE;
- #[cfg(not(any(apple, target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- use c::TCP_KEEPIDLE;
- use core::time::Duration;
- #[cfg(windows)]
- use windows_sys::Win32::Foundation::BOOL;
-
- #[inline]
- fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result<T> {
- use super::*;
-
- let mut optlen = core::mem::size_of::<T>().try_into().unwrap();
- debug_assert!(
- optlen as usize >= core::mem::size_of::<c::c_int>(),
- "Socket APIs don't ever use `bool` directly"
- );
-
- unsafe {
- let mut value = core::mem::zeroed::<T>();
- ret(c::getsockopt(
- borrowed_fd(fd),
- level,
- optname,
- as_mut_ptr(&mut value).cast(),
- &mut optlen,
- ))?;
- // On Windows at least, `getsockopt` has been observed writing 1
- // byte on at least (`IPPROTO_TCP`, `TCP_NODELAY`), even though
- // Windows' documentation says that should write a 4-byte `BOOL`.
- // So, we initialize the memory to zeros above, and just assert
- // that `getsockopt` doesn't write too many bytes here.
- assert!(
- optlen as usize <= size_of::<T>(),
- "unexpected getsockopt size"
- );
- Ok(value)
- }
- }
-
- #[inline]
- fn setsockopt<T: Copy>(
- fd: BorrowedFd<'_>,
- level: i32,
- optname: i32,
- value: T,
- ) -> io::Result<()> {
- use super::*;
-
- let optlen = core::mem::size_of::<T>().try_into().unwrap();
- debug_assert!(
- optlen as usize >= core::mem::size_of::<c::c_int>(),
- "Socket APIs don't ever use `bool` directly"
- );
-
- unsafe {
- ret(c::setsockopt(
- borrowed_fd(fd),
- level,
- optname,
- as_ptr(&value).cast(),
- optlen,
- ))
- }
- }
-
- #[inline]
- pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result<SocketType> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_TYPE)
- }
-
- #[inline]
- pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
- setsockopt(
- fd,
- c::SOL_SOCKET as _,
- c::SO_REUSEADDR,
- from_bool(reuseaddr),
- )
- }
-
- #[inline]
- pub(crate) fn get_socket_reuseaddr(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_REUSEADDR).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
- setsockopt(
- fd,
- c::SOL_SOCKET as _,
- c::SO_BROADCAST,
- from_bool(broadcast),
- )
- }
-
- #[inline]
- pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_socket_linger(
- fd: BorrowedFd<'_>,
- linger: Option<Duration>,
- ) -> io::Result<()> {
- // Convert `linger` to seconds, rounding up.
- let l_linger = if let Some(linger) = linger {
- duration_to_secs(linger)?
- } else {
- 0
- };
- let linger = c::linger {
- l_onoff: linger.is_some() as _,
- l_linger,
- };
- setsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER, linger)
- }
-
- #[inline]
- pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result<Option<Duration>> {
- let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?;
- Ok((linger.l_onoff != 0).then(|| Duration::from_secs(linger.l_linger as u64)))
- }
-
- #[cfg(linux_kernel)]
- #[inline]
- pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> {
- setsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED, from_bool(passcred))
- }
-
- #[cfg(linux_kernel)]
- #[inline]
- pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_socket_timeout(
- fd: BorrowedFd<'_>,
- id: Timeout,
- timeout: Option<Duration>,
- ) -> io::Result<()> {
- let optname = match id {
- Timeout::Recv => c::SO_RCVTIMEO,
- Timeout::Send => c::SO_SNDTIMEO,
- };
-
- #[cfg(not(windows))]
- let timeout = match timeout {
- Some(timeout) => {
- if timeout == Duration::ZERO {
- return Err(io::Errno::INVAL);
- }
-
- // Rust's musl libc bindings deprecated `time_t` while they
- // transition to 64-bit `time_t`. What we want here is just
- // “whatever type `timeval`'s `tv_sec` is”, so we're ok using
- // the deprecated type.
- #[allow(deprecated)]
- let tv_sec = timeout.as_secs().try_into().unwrap_or(c::time_t::MAX);
-
- // `subsec_micros` rounds down, so we use `subsec_nanos` and
- // manually round up.
- let mut timeout = c::timeval {
- tv_sec,
- tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _,
- };
- if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
- timeout.tv_usec = 1;
- }
- timeout
- }
- None => c::timeval {
- tv_sec: 0,
- tv_usec: 0,
- },
- };
-
- #[cfg(windows)]
- let timeout: u32 = match timeout {
- Some(timeout) => {
- if timeout == Duration::ZERO {
- return Err(io::Errno::INVAL);
- }
-
- // `as_millis` rounds down, so we use `as_nanos` and
- // manually round up.
- let mut timeout: u32 = ((timeout.as_nanos() + 999_999) / 1_000_000)
- .try_into()
- .map_err(|_convert_err| io::Errno::INVAL)?;
- if timeout == 0 {
- timeout = 1;
- }
- timeout
- }
- None => 0,
- };
-
- setsockopt(fd, c::SOL_SOCKET, optname, timeout)
- }
-
- #[inline]
- pub(crate) fn get_socket_timeout(
- fd: BorrowedFd<'_>,
- id: Timeout,
- ) -> io::Result<Option<Duration>> {
- let optname = match id {
- Timeout::Recv => c::SO_RCVTIMEO,
- Timeout::Send => c::SO_SNDTIMEO,
- };
-
- #[cfg(not(windows))]
- {
- let timeout: c::timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
- if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
- Ok(None)
- } else {
- Ok(Some(
- Duration::from_secs(timeout.tv_sec as u64)
- + Duration::from_micros(timeout.tv_usec as u64),
- ))
- }
- }
-
- #[cfg(windows)]
- {
- let timeout: u32 = getsockopt(fd, c::SOL_SOCKET, optname)?;
- if timeout == 0 {
- Ok(None)
- } else {
- Ok(Some(Duration::from_millis(timeout as u64)))
- }
- }
- }
-
- #[cfg(any(apple, target_os = "freebsd"))]
- #[inline]
- pub(crate) fn get_socket_nosigpipe(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE).map(to_bool)
- }
-
- #[cfg(any(apple, target_os = "freebsd"))]
- #[inline]
- pub(crate) fn set_socket_nosigpipe(fd: BorrowedFd<'_>, val: bool) -> io::Result<()> {
- setsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE, from_bool(val))
- }
-
- #[inline]
- pub(crate) fn get_socket_error(fd: BorrowedFd<'_>) -> io::Result<Result<(), io::Errno>> {
- let err: c::c_int = getsockopt(fd, c::SOL_SOCKET as _, c::SO_ERROR)?;
- Ok(if err == 0 {
- Ok(())
- } else {
- Err(io::Errno::from_raw_os_error(err))
- })
- }
-
- #[inline]
- pub(crate) fn set_socket_keepalive(fd: BorrowedFd<'_>, keepalive: bool) -> io::Result<()> {
- setsockopt(
- fd,
- c::SOL_SOCKET as _,
- c::SO_KEEPALIVE,
- from_bool(keepalive),
- )
- }
-
- #[inline]
- pub(crate) fn get_socket_keepalive(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_KEEPALIVE).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_socket_recv_buffer_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
- let size: c::c_int = size.try_into().map_err(|_| io::Errno::INVAL)?;
- setsockopt(fd, c::SOL_SOCKET as _, c::SO_RCVBUF, size)
- }
-
- #[inline]
- pub(crate) fn get_socket_recv_buffer_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_RCVBUF).map(|size: u32| size as usize)
- }
-
- #[inline]
- pub(crate) fn set_socket_send_buffer_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
- let size: c::c_int = size.try_into().map_err(|_| io::Errno::INVAL)?;
- setsockopt(fd, c::SOL_SOCKET as _, c::SO_SNDBUF, size)
- }
-
- #[inline]
- pub(crate) fn get_socket_send_buffer_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_SNDBUF).map(|size: u32| size as usize)
- }
-
- #[inline]
- #[cfg(not(any(
- apple,
- windows,
- target_os = "aix",
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "espidf",
- target_os = "haiku",
- target_os = "netbsd",
- target_os = "nto",
- )))]
- pub(crate) fn get_socket_domain(fd: BorrowedFd<'_>) -> io::Result<AddressFamily> {
- let domain: c::c_int = getsockopt(fd, c::SOL_SOCKET as _, c::SO_DOMAIN)?;
- Ok(AddressFamily(
- domain.try_into().map_err(|_| io::Errno::OPNOTSUPP)?,
- ))
- }
-
- #[inline]
- #[cfg(not(apple))] // Apple platforms declare the constant, but do not actually implement it.
- pub(crate) fn get_socket_acceptconn(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::SOL_SOCKET as _, c::SO_ACCEPTCONN).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
- setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
- }
-
- #[inline]
- pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
- getsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
- setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY, from_bool(only_v6))
- }
-
- #[inline]
- pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_ip_multicast_loop(
- fd: BorrowedFd<'_>,
- multicast_loop: bool,
- ) -> io::Result<()> {
- setsockopt(
- fd,
- c::IPPROTO_IP as _,
- c::IP_MULTICAST_LOOP,
- from_bool(multicast_loop),
- )
- }
-
- #[inline]
- pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_LOOP).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
- setsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL, multicast_ttl)
- }
-
- #[inline]
- pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
- getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_multicast_loop(
- fd: BorrowedFd<'_>,
- multicast_loop: bool,
- ) -> io::Result<()> {
- setsockopt(
- fd,
- c::IPPROTO_IPV6 as _,
- c::IPV6_MULTICAST_LOOP,
- from_bool(multicast_loop),
- )
- }
-
- #[inline]
- pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_MULTICAST_LOOP).map(to_bool)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_multicast_hops(
- fd: BorrowedFd<'_>,
- multicast_hops: u32,
- ) -> io::Result<()> {
- setsockopt(
- fd,
- c::IPPROTO_IP as _,
- c::IPV6_MULTICAST_HOPS,
- multicast_hops,
- )
- }
-
- #[inline]
- pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result<u32> {
- getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_HOPS)
- }
-
- #[inline]
- pub(crate) fn set_ip_add_membership(
- fd: BorrowedFd<'_>,
- multiaddr: &Ipv4Addr,
- interface: &Ipv4Addr,
- ) -> io::Result<()> {
- let mreq = to_imr(multiaddr, interface);
- setsockopt(fd, c::IPPROTO_IP as _, c::IP_ADD_MEMBERSHIP, mreq)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_add_membership(
- fd: BorrowedFd<'_>,
- multiaddr: &Ipv6Addr,
- interface: u32,
- ) -> io::Result<()> {
- #[cfg(not(any(
- bsd,
- solarish,
- target_os = "haiku",
- target_os = "l4re",
- target_os = "nto"
- )))]
- use c::IPV6_ADD_MEMBERSHIP;
- #[cfg(any(
- bsd,
- solarish,
- target_os = "haiku",
- target_os = "l4re",
- target_os = "nto"
- ))]
- use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
-
- let mreq = to_ipv6mr(multiaddr, interface);
- setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_ADD_MEMBERSHIP, mreq)
- }
-
- #[inline]
- pub(crate) fn set_ip_drop_membership(
- fd: BorrowedFd<'_>,
- multiaddr: &Ipv4Addr,
- interface: &Ipv4Addr,
- ) -> io::Result<()> {
- let mreq = to_imr(multiaddr, interface);
- setsockopt(fd, c::IPPROTO_IP as _, c::IP_DROP_MEMBERSHIP, mreq)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_drop_membership(
- fd: BorrowedFd<'_>,
- multiaddr: &Ipv6Addr,
- interface: u32,
- ) -> io::Result<()> {
- #[cfg(not(any(
- bsd,
- solarish,
- target_os = "haiku",
- target_os = "l4re",
- target_os = "nto"
- )))]
- use c::IPV6_DROP_MEMBERSHIP;
- #[cfg(any(
- bsd,
- solarish,
- target_os = "haiku",
- target_os = "l4re",
- target_os = "nto"
- ))]
- use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
-
- let mreq = to_ipv6mr(multiaddr, interface);
- setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_DROP_MEMBERSHIP, mreq)
- }
-
- #[inline]
- pub(crate) fn get_ipv6_unicast_hops(fd: BorrowedFd<'_>) -> io::Result<u8> {
- getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_UNICAST_HOPS).map(|hops: c::c_int| hops as u8)
- }
-
- #[inline]
- pub(crate) fn set_ipv6_unicast_hops(fd: BorrowedFd<'_>, hops: Option<u8>) -> io::Result<()> {
- let hops = match hops {
- Some(hops) => hops as c::c_int,
- None => -1,
- };
- setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_UNICAST_HOPS, hops)
- }
-
- #[inline]
- pub(crate) fn set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
- setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY, from_bool(nodelay))
- }
-
- #[inline]
- pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
- getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool)
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn set_tcp_keepcnt(fd: BorrowedFd<'_>, count: u32) -> io::Result<()> {
- setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_KEEPCNT, count)
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn get_tcp_keepcnt(fd: BorrowedFd<'_>) -> io::Result<u32> {
- getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_KEEPCNT)
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn set_tcp_keepidle(fd: BorrowedFd<'_>, duration: Duration) -> io::Result<()> {
- let secs: c::c_uint = duration_to_secs(duration)?;
- setsockopt(fd, c::IPPROTO_TCP as _, TCP_KEEPIDLE, secs)
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn get_tcp_keepidle(fd: BorrowedFd<'_>) -> io::Result<Duration> {
- let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP as _, TCP_KEEPIDLE)?;
- Ok(Duration::from_secs(secs as u64))
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn set_tcp_keepintvl(fd: BorrowedFd<'_>, duration: Duration) -> io::Result<()> {
- let secs: c::c_uint = duration_to_secs(duration)?;
- setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_KEEPINTVL, secs)
- }
-
- #[inline]
- #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
- pub(crate) fn get_tcp_keepintvl(fd: BorrowedFd<'_>) -> io::Result<Duration> {
- let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_KEEPINTVL)?;
- Ok(Duration::from_secs(secs as u64))
- }
-
- #[inline]
- fn to_imr(multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> c::ip_mreq {
- c::ip_mreq {
- imr_multiaddr: to_imr_addr(multiaddr),
- imr_interface: to_imr_addr(interface),
- }
- }
-
- #[inline]
- fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr {
- in_addr_new(u32::from_ne_bytes(addr.octets()))
- }
-
- #[inline]
- fn to_ipv6mr(multiaddr: &Ipv6Addr, interface: u32) -> c::ipv6_mreq {
- c::ipv6_mreq {
- ipv6mr_multiaddr: to_ipv6mr_multiaddr(multiaddr),
- ipv6mr_interface: to_ipv6mr_interface(interface),
- }
- }
-
- #[inline]
- fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr {
- in6_addr_new(multiaddr.octets())
- }
-
- #[cfg(target_os = "android")]
- #[inline]
- fn to_ipv6mr_interface(interface: u32) -> c::c_int {
- interface as c::c_int
- }
-
- #[cfg(not(target_os = "android"))]
- #[inline]
- fn to_ipv6mr_interface(interface: u32) -> c::c_uint {
- interface as c::c_uint
- }
-
- // `getsockopt` and `setsockopt` represent boolean values as integers.
- #[cfg(not(windows))]
- type RawSocketBool = c::c_int;
- #[cfg(windows)]
- type RawSocketBool = BOOL;
-
- // Wrap `RawSocketBool` in a newtype to discourage misuse.
- #[repr(transparent)]
- #[derive(Copy, Clone)]
- struct SocketBool(RawSocketBool);
-
- // Convert from a `bool` to a `SocketBool`.
- #[inline]
- fn from_bool(value: bool) -> SocketBool {
- SocketBool(value as _)
- }
-
- // Convert from a `SocketBool` to a `bool`.
- #[inline]
- fn to_bool(value: SocketBool) -> bool {
- value.0 != 0
- }
-
- /// Convert to seconds, rounding up if necessary.
- #[inline]
- fn duration_to_secs<T: TryFrom<u64>>(duration: Duration) -> io::Result<T> {
- let mut secs = duration.as_secs();
- if duration.subsec_nanos() != 0 {
- secs = secs.checked_add(1).ok_or(io::Errno::INVAL)?;
- }
- T::try_from(secs).map_err(|_e| io::Errno::INVAL)
- }
-}
diff --git a/vendor/rustix/src/backend/libc/net/write_sockaddr.rs b/vendor/rustix/src/backend/libc/net/write_sockaddr.rs
index a354d9a85..2eee98cb8 100644
--- a/vendor/rustix/src/backend/libc/net/write_sockaddr.rs
+++ b/vendor/rustix/src/backend/libc/net/write_sockaddr.rs
@@ -1,5 +1,5 @@
-//! The BSD sockets API requires us to read the `ss_family` field before
-//! we can interpret the rest of a `sockaddr` produced by the kernel.
+//! The BSD sockets API requires us to read the `ss_family` field before we can
+//! interpret the rest of a `sockaddr` produced by the kernel.
use super::addr::SocketAddrStorage;
#[cfg(unix)]
@@ -29,15 +29,20 @@ pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
target_os = "espidf",
target_os = "haiku",
target_os = "nto",
+ target_os = "vita",
))]
sin_len: size_of::<c::sockaddr_in>() as _,
sin_family: c::AF_INET as _,
sin_port: u16::to_be(v4.port()),
sin_addr: in_addr_new(u32::from_ne_bytes(v4.ip().octets())),
- #[cfg(not(target_os = "haiku"))]
+ #[cfg(not(any(target_os = "haiku", target_os = "vita")))]
sin_zero: [0; 8_usize],
#[cfg(target_os = "haiku")]
sin_zero: [0; 24_usize],
+ #[cfg(target_os = "vita")]
+ sin_zero: [0; 6_usize],
+ #[cfg(target_os = "vita")]
+ sin_vport: 0,
}
}
@@ -54,6 +59,7 @@ pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
target_os = "espidf",
target_os = "haiku",
target_os = "nto",
+ target_os = "vita"
))]
{
sockaddr_in6_new(
@@ -70,7 +76,8 @@ pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
target_os = "aix",
target_os = "espidf",
target_os = "haiku",
- target_os = "nto"
+ target_os = "nto",
+ target_os = "vita"
)))]
{
sockaddr_in6_new(