diff --git a/src/backend/libc/net/mod.rs b/src/backend/libc/net/mod.rs index 65c7d0654..c425ec01f 100644 --- a/src/backend/libc/net/mod.rs +++ b/src/backend/libc/net/mod.rs @@ -4,5 +4,7 @@ pub(crate) mod ext; 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/src/backend/libc/net/sockopt.rs b/src/backend/libc/net/sockopt.rs new file mode 100644 index 000000000..29c87f541 --- /dev/null +++ b/src/backend/libc/net/sockopt.rs @@ -0,0 +1,768 @@ +//! 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; +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, as_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::mem::size_of; +use core::time::Duration; +#[cfg(windows)] +use windows_sys::Win32::Foundation::BOOL; + +#[inline] +fn getsockopt(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result { + let mut optlen = core::mem::size_of::().try_into().unwrap(); + debug_assert!( + optlen as usize >= core::mem::size_of::(), + "Socket APIs don't ever use `bool` directly" + ); + + unsafe { + let mut value = core::mem::zeroed::(); + 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::(), + "unexpected getsockopt size" + ); + Ok(value) + } +} + +#[inline] +fn setsockopt(fd: BorrowedFd<'_>, level: i32, optname: i32, value: T) -> io::Result<()> { + let optlen = core::mem::size_of::().try_into().unwrap(); + debug_assert!( + optlen as usize >= core::mem::size_of::(), + "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 { + 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 { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_BROADCAST).map(to_bool) +} + +#[inline] +pub(crate) fn set_socket_linger(fd: BorrowedFd<'_>, linger: Option) -> 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> { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_PASSCRED).map(to_bool) +} + +#[inline] +pub(crate) fn set_socket_timeout( + fd: BorrowedFd<'_>, + id: Timeout, + timeout: Option, +) -> 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> { + 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 { + 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> { + 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 { + 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 { + 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 { + 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", +)))] +pub(crate) fn get_socket_domain(fd: BorrowedFd<'_>) -> io::Result { + 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 { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_OOBINLINE).map(to_bool) +} + +#[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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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) -> 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 { + 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 { + 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 { + getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_RECVTCLASS).map(to_bool) +} + +#[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 { + 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 { + 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 { + 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 { + 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 { + getsockopt(fd, c::IPPROTO_TCP, c::TCP_USER_TIMEOUT) +} + +#[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>(duration: Duration) -> io::Result { + 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/src/backend/libc/net/syscalls.rs b/src/backend/libc/net/syscalls.rs index 2e968ba3e..94248c5d8 100644 --- a/src/backend/libc/net/syscalls.rs +++ b/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}; @@ -515,636 +514,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(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result { - use super::*; - - let mut optlen = core::mem::size_of::().try_into().unwrap(); - debug_assert!( - optlen as usize >= core::mem::size_of::(), - "Socket APIs don't ever use `bool` directly" - ); - - unsafe { - let mut value = core::mem::zeroed::(); - 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::(), - "unexpected getsockopt size" - ); - Ok(value) - } - } - - #[inline] - fn setsockopt( - fd: BorrowedFd<'_>, - level: i32, - optname: i32, - value: T, - ) -> io::Result<()> { - use super::*; - - let optlen = core::mem::size_of::().try_into().unwrap(); - debug_assert!( - optlen as usize >= core::mem::size_of::(), - "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 { - 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 { - 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 { - getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool) - } - - #[inline] - pub(crate) fn set_socket_linger( - fd: BorrowedFd<'_>, - linger: Option, - ) -> 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> { - 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 { - 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, - ) -> 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> { - 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 { - 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> { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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) -> 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 { - 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 { - 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 { - 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 { - 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>(duration: Duration) -> io::Result { - 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/src/backend/linux_raw/c.rs b/src/backend/linux_raw/c.rs index 0db4e2836..80fbbc141 100644 --- a/src/backend/linux_raw/c.rs +++ b/src/backend/linux_raw/c.rs @@ -51,31 +51,86 @@ pub(crate) use linux_raw_sys::{ general::{O_CLOEXEC as SOCK_CLOEXEC, O_NONBLOCK as SOCK_NONBLOCK}, if_ether::*, net::{ - AF_DECnet, __kernel_sa_family_t as sa_family_t, - __kernel_sockaddr_storage as sockaddr_storage, cmsghdr, in6_addr, in_addr, ip_mreq, - ipv6_mreq, linger, msghdr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t, - AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH, AF_BRIDGE, AF_CAN, - AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN, AF_IUCV, AF_KEY, - AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX, AF_RDS, AF_ROSE, - AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE, AF_X25, IPPROTO_AH, - IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, IPPROTO_ENCAP, IPPROTO_ESP, - IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, IPPROTO_ICMPV6, IPPROTO_IDP, - IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, IPPROTO_MPLS, - IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING, - IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, IPPROTO_UDPLITE, - IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, - IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, - IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, + linger, msghdr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t, AF_DECnet, + __kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage, + cmsghdr, in6_addr, in_addr, ip_mreq, ip_mreq_source, ip_mreqn, ipv6_mreq, AF_APPLETALK, + AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH, AF_BRIDGE, AF_CAN, AF_ECONET, + AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN, AF_IUCV, AF_KEY, AF_LLC, + AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX, AF_RDS, AF_ROSE, + AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE, AF_X25, + IPPROTO_FRAGMENT, IPPROTO_ICMPV6, IPPROTO_MH, IPPROTO_ROUTING, IPV6_ADD_MEMBERSHIP, + IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, IPV6_RECVTCLASS, + IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, + IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, + IP_RECVTOS, IP_TOS, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, SCM_CREDENTIALS, SCM_RIGHTS, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, - SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_DOMAIN, SO_ERROR, SO_KEEPALIVE, - SO_LINGER, SO_PASSCRED, SO_RCVBUF, SO_RCVTIMEO_NEW, SO_RCVTIMEO_NEW as SO_RCVTIMEO, - SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO_NEW, SO_SNDTIMEO_NEW as SO_SNDTIMEO, - SO_SNDTIMEO_OLD, SO_TYPE, TCP_NODELAY, + SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_ACCEPTCONN, SO_BROADCAST, SO_DOMAIN, SO_ERROR, + SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_PASSCRED, SO_RCVBUF, SO_RCVTIMEO_NEW, + SO_RCVTIMEO_NEW as SO_RCVTIMEO, SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO_NEW, + SO_SNDTIMEO_NEW as SO_SNDTIMEO, SO_SNDTIMEO_OLD, SO_TYPE, TCP_KEEPCNT, TCP_KEEPIDLE, + TCP_KEEPINTVL, TCP_NODELAY, TCP_USER_TIMEOUT, }, netlink::*, }; +// Cast away bindgen's `enum` type to make these consistent with the other +// `setsockopt`/`getsockopt` level values. +#[cfg(feature = "net")] +pub(crate) const IPPROTO_IP: u32 = linux_raw_sys::net::IPPROTO_IP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_ICMP: u32 = linux_raw_sys::net::IPPROTO_ICMP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_IGMP: u32 = linux_raw_sys::net::IPPROTO_IGMP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_IPIP: u32 = linux_raw_sys::net::IPPROTO_IPIP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_TCP: u32 = linux_raw_sys::net::IPPROTO_TCP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_EGP: u32 = linux_raw_sys::net::IPPROTO_EGP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_PUP: u32 = linux_raw_sys::net::IPPROTO_PUP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_UDP: u32 = linux_raw_sys::net::IPPROTO_UDP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_IDP: u32 = linux_raw_sys::net::IPPROTO_IDP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_TP: u32 = linux_raw_sys::net::IPPROTO_TP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_DCCP: u32 = linux_raw_sys::net::IPPROTO_DCCP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_IPV6: u32 = linux_raw_sys::net::IPPROTO_IPV6 as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_RSVP: u32 = linux_raw_sys::net::IPPROTO_RSVP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_GRE: u32 = linux_raw_sys::net::IPPROTO_GRE as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_ESP: u32 = linux_raw_sys::net::IPPROTO_ESP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_AH: u32 = linux_raw_sys::net::IPPROTO_AH as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_MTP: u32 = linux_raw_sys::net::IPPROTO_MTP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_BEETPH: u32 = linux_raw_sys::net::IPPROTO_BEETPH as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_ENCAP: u32 = linux_raw_sys::net::IPPROTO_ENCAP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_PIM: u32 = linux_raw_sys::net::IPPROTO_PIM as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_COMP: u32 = linux_raw_sys::net::IPPROTO_COMP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_SCTP: u32 = linux_raw_sys::net::IPPROTO_SCTP as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_UDPLITE: u32 = linux_raw_sys::net::IPPROTO_UDPLITE as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_MPLS: u32 = linux_raw_sys::net::IPPROTO_MPLS as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_ETHERNET: u32 = linux_raw_sys::net::IPPROTO_ETHERNET as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_RAW: u32 = linux_raw_sys::net::IPPROTO_RAW as _; +#[cfg(feature = "net")] +pub(crate) const IPPROTO_MPTCP: u32 = linux_raw_sys::net::IPPROTO_MPTCP as _; + #[cfg(any(feature = "process", feature = "runtime"))] pub(crate) use linux_raw_sys::general::siginfo_t; diff --git a/src/backend/linux_raw/net/mod.rs b/src/backend/linux_raw/net/mod.rs index 2b6ab34ba..f83c54621 100644 --- a/src/backend/linux_raw/net/mod.rs +++ b/src/backend/linux_raw/net/mod.rs @@ -2,5 +2,6 @@ pub(crate) mod addr; pub(crate) mod msghdr; pub(crate) mod read_sockaddr; pub(crate) mod send_recv; +pub(crate) mod sockopt; pub(crate) mod syscalls; pub(crate) mod write_sockaddr; diff --git a/src/backend/linux_raw/net/sockopt.rs b/src/backend/linux_raw/net/sockopt.rs new file mode 100644 index 000000000..24cabbe5e --- /dev/null +++ b/src/backend/linux_raw/net/sockopt.rs @@ -0,0 +1,693 @@ +//! linux_raw syscalls supporting `rustix::net::sockopt`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::{by_mut, by_ref, c_uint, ret, socklen_t}; +use crate::fd::BorrowedFd; +use crate::io; +use crate::net::sockopt::Timeout; +use crate::net::{AddressFamily, Ipv4Addr, Ipv6Addr, SocketType}; +use core::mem::MaybeUninit; +use core::time::Duration; +use linux_raw_sys::general::{__kernel_old_timeval, __kernel_sock_timeval}; +#[cfg(target_arch = "x86")] +use { + crate::backend::conv::{slice_just_addr, x86_sys}, + crate::backend::reg::{ArgReg, SocketArg}, + linux_raw_sys::net::{SYS_GETSOCKOPT, SYS_SETSOCKOPT}, +}; + +#[inline] +fn getsockopt(fd: BorrowedFd<'_>, level: u32, optname: u32) -> io::Result { + let mut optlen = core::mem::size_of::(); + debug_assert!( + optlen as usize >= core::mem::size_of::(), + "Socket APIs don't ever use `bool` directly" + ); + + #[cfg(not(target_arch = "x86"))] + unsafe { + let mut value = MaybeUninit::::uninit(); + ret(syscall!( + __NR_getsockopt, + fd, + c_uint(level), + c_uint(optname), + &mut value, + by_mut(&mut optlen) + ))?; + + assert_eq!( + optlen as usize, + core::mem::size_of::(), + "unexpected getsockopt size" + ); + Ok(value.assume_init()) + } + #[cfg(target_arch = "x86")] + unsafe { + let mut value = MaybeUninit::::uninit(); + ret(syscall!( + __NR_socketcall, + x86_sys(SYS_GETSOCKOPT), + slice_just_addr::, _>(&[ + fd.into(), + c_uint(level), + c_uint(optname), + (&mut value).into(), + by_mut(&mut optlen), + ]) + ))?; + assert_eq!( + optlen as usize, + core::mem::size_of::(), + "unexpected getsockopt size" + ); + Ok(value.assume_init()) + } +} + +#[inline] +fn setsockopt(fd: BorrowedFd<'_>, level: u32, optname: u32, value: T) -> io::Result<()> { + let optlen = core::mem::size_of::().try_into().unwrap(); + debug_assert!( + optlen as usize >= core::mem::size_of::(), + "Socket APIs don't ever use `bool` directly" + ); + + #[cfg(not(target_arch = "x86"))] + unsafe { + ret(syscall_readonly!( + __NR_setsockopt, + fd, + c_uint(level), + c_uint(optname), + by_ref(&value), + socklen_t(optlen) + )) + } + #[cfg(target_arch = "x86")] + unsafe { + ret(syscall_readonly!( + __NR_socketcall, + x86_sys(SYS_SETSOCKOPT), + slice_just_addr::, _>(&[ + fd.into(), + c_uint(level), + c_uint(optname), + by_ref(&value), + socklen_t(optlen), + ]) + )) + } +} + +#[inline] +pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result { + 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 { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_BROADCAST).map(to_bool) +} + +#[inline] +pub(crate) fn set_socket_linger(fd: BorrowedFd<'_>, linger: Option) -> 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: c::c_int::from(linger.is_some()), + l_linger, + }; + setsockopt(fd, c::SOL_SOCKET, c::SO_LINGER, linger) +} + +#[inline] +pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result> { + 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))) +} + +#[inline] +pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> { + setsockopt(fd, c::SOL_SOCKET, c::SO_PASSCRED, from_bool(passcred)) +} + +#[inline] +pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result { + getsockopt(fd, c::SOL_SOCKET, c::SO_PASSCRED).map(to_bool) +} + +#[inline] +pub(crate) fn set_socket_timeout( + fd: BorrowedFd<'_>, + id: Timeout, + timeout: Option, +) -> io::Result<()> { + let time = duration_to_linux_sock_timeval(timeout)?; + let optname = match id { + Timeout::Recv => c::SO_RCVTIMEO_NEW, + Timeout::Send => c::SO_SNDTIMEO_NEW, + }; + match setsockopt(fd, c::SOL_SOCKET, optname, time) { + Err(io::Errno::NOPROTOOPT) if c::SO_RCVTIMEO_NEW != c::SO_RCVTIMEO_OLD => { + set_socket_timeout_old(fd, id, timeout) + } + otherwise => otherwise, + } +} + +/// Same as `set_socket_timeout` but uses `__kernel_old_timeval` instead of +/// `__kernel_sock_timeval` and `_OLD` constants instead of `_NEW`. +fn set_socket_timeout_old( + fd: BorrowedFd<'_>, + id: Timeout, + timeout: Option, +) -> io::Result<()> { + let time = duration_to_linux_old_timeval(timeout)?; + let optname = match id { + Timeout::Recv => c::SO_RCVTIMEO_OLD, + Timeout::Send => c::SO_SNDTIMEO_OLD, + }; + setsockopt(fd, c::SOL_SOCKET, optname, time) +} + +#[inline] +pub(crate) fn get_socket_timeout(fd: BorrowedFd<'_>, id: Timeout) -> io::Result> { + let optname = match id { + Timeout::Recv => c::SO_RCVTIMEO_NEW, + Timeout::Send => c::SO_SNDTIMEO_NEW, + }; + let time: __kernel_sock_timeval = match getsockopt(fd, c::SOL_SOCKET, optname) { + Err(io::Errno::NOPROTOOPT) if c::SO_RCVTIMEO_NEW != c::SO_RCVTIMEO_OLD => { + return get_socket_timeout_old(fd, id) + } + otherwise => otherwise?, + }; + Ok(duration_from_linux_sock_timeval(time)) +} + +/// Same as `get_socket_timeout` but uses `__kernel_old_timeval` instead of +/// `__kernel_sock_timeval` and `_OLD` constants instead of `_NEW`. +fn get_socket_timeout_old(fd: BorrowedFd<'_>, id: Timeout) -> io::Result> { + let optname = match id { + Timeout::Recv => c::SO_RCVTIMEO_OLD, + Timeout::Send => c::SO_SNDTIMEO_OLD, + }; + let time: __kernel_old_timeval = getsockopt(fd, c::SOL_SOCKET, optname)?; + Ok(duration_from_linux_old_timeval(time)) +} + +/// Convert a `__linux_sock_timeval` to a Rust `Option`. +#[inline] +fn duration_from_linux_sock_timeval(time: __kernel_sock_timeval) -> Option { + if time.tv_sec == 0 && time.tv_usec == 0 { + None + } else { + Some(Duration::from_secs(time.tv_sec as u64) + Duration::from_micros(time.tv_usec as u64)) + } +} + +/// Like `duration_from_linux` but uses Linux's old 32-bit +/// `__kernel_old_timeval`. +fn duration_from_linux_old_timeval(time: __kernel_old_timeval) -> Option { + if time.tv_sec == 0 && time.tv_usec == 0 { + None + } else { + Some(Duration::from_secs(time.tv_sec as u64) + Duration::from_micros(time.tv_usec as u64)) + } +} + +/// Convert a Rust `Option` to a `__kernel_sock_timeval`. +#[inline] +fn duration_to_linux_sock_timeval(timeout: Option) -> io::Result<__kernel_sock_timeval> { + Ok(match timeout { + Some(timeout) => { + if timeout == Duration::ZERO { + return Err(io::Errno::INVAL); + } + // `subsec_micros` rounds down, so we use `subsec_nanos` and + // manually round up. + let mut timeout = __kernel_sock_timeval { + tv_sec: timeout.as_secs().try_into().unwrap_or(i64::MAX), + tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _, + }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + timeout + } + None => __kernel_sock_timeval { + tv_sec: 0, + tv_usec: 0, + }, + }) +} + +/// Like `duration_to_linux` but uses Linux's old 32-bit +/// `__kernel_old_timeval`. +fn duration_to_linux_old_timeval(timeout: Option) -> io::Result<__kernel_old_timeval> { + Ok(match timeout { + Some(timeout) => { + if timeout == Duration::ZERO { + return Err(io::Errno::INVAL); + } + + // `subsec_micros` rounds down, so we use `subsec_nanos` and + // manually round up. + let mut timeout = __kernel_old_timeval { + tv_sec: timeout.as_secs().try_into().unwrap_or(c::c_long::MAX), + tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _, + }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + timeout + } + None => __kernel_old_timeval { + tv_sec: 0, + tv_usec: 0, + }, + }) +} + +#[inline] +pub(crate) fn get_socket_error(fd: BorrowedFd<'_>) -> io::Result> { + 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 { + 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 { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_SNDBUF).map(|size: u32| size as usize) +} + +#[inline] +pub(crate) fn get_socket_domain(fd: BorrowedFd<'_>) -> io::Result { + let domain: c::c_int = getsockopt(fd, c::SOL_SOCKET, c::SO_DOMAIN)?; + Ok(AddressFamily( + domain.try_into().map_err(|_| io::Errno::OPNOTSUPP)?, + )) +} + +#[inline] +pub(crate) fn get_socket_acceptconn(fd: BorrowedFd<'_>) -> io::Result { + 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 { + getsockopt(fd, c::SOL_SOCKET, c::SO_OOBINLINE).map(to_bool) +} + +#[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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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) +} + +#[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) +} + +#[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) +} + +#[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<()> { + let mreq = to_ipv6mr(multiaddr, interface); + setsockopt(fd, c::IPPROTO_IPV6, c::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) +} + +#[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<()> { + let mreq = to_ipv6mr(multiaddr, interface); + setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_DROP_MEMBERSHIP, mreq) +} + +#[inline] +pub(crate) fn get_ipv6_unicast_hops(fd: BorrowedFd<'_>) -> io::Result { + 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) -> io::Result<()> { + let hops = match hops { + Some(hops) => hops.into(), + None => -1, + }; + setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, hops) +} + +#[inline] +pub(crate) fn set_ip_tos(fd: BorrowedFd<'_>, value: u8) -> io::Result<()> { + setsockopt(fd, c::IPPROTO_IP, c::IP_TOS, i32::from(value)) +} + +#[inline] +pub(crate) fn get_ip_tos(fd: BorrowedFd<'_>) -> io::Result { + let value: i32 = getsockopt(fd, c::IPPROTO_IP, c::IP_TOS)?; + Ok(value as u8) +} + +#[inline] +pub(crate) fn set_ip_recvtos(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { + setsockopt(fd, c::IPPROTO_IP, c::IP_RECVTOS, from_bool(value)) +} + +#[inline] +pub(crate) fn get_ip_recvtos(fd: BorrowedFd<'_>) -> io::Result { + getsockopt(fd, c::IPPROTO_IP, c::IP_RECVTOS).map(to_bool) +} + +#[inline] +pub(crate) fn set_ipv6_recvtclass(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { + setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_RECVTCLASS, from_bool(value)) +} + +#[inline] +pub(crate) fn get_ipv6_recvtclass(fd: BorrowedFd<'_>) -> io::Result { + getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_RECVTCLASS).map(to_bool) +} + +#[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 { + getsockopt(fd, c::IPPROTO_TCP, c::TCP_NODELAY).map(to_bool) +} + +#[inline] +pub(crate) fn set_tcp_keepcnt(fd: BorrowedFd<'_>, count: u32) -> io::Result<()> { + setsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPCNT, count) +} + +#[inline] +pub(crate) fn get_tcp_keepcnt(fd: BorrowedFd<'_>) -> io::Result { + getsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPCNT) +} + +#[inline] +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, c::TCP_KEEPIDLE, secs) +} + +#[inline] +pub(crate) fn get_tcp_keepidle(fd: BorrowedFd<'_>) -> io::Result { + let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPIDLE)?; + Ok(Duration::from_secs(secs as u64)) +} + +#[inline] +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] +pub(crate) fn get_tcp_keepintvl(fd: BorrowedFd<'_>) -> io::Result { + let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP, c::TCP_KEEPINTVL)?; + Ok(Duration::from_secs(secs as u64)) +} + +#[inline] +pub(crate) fn set_tcp_user_timeout(fd: BorrowedFd<'_>, value: u32) -> io::Result<()> { + setsockopt(fd, c::IPPROTO_TCP, c::TCP_USER_TIMEOUT, value) +} + +#[inline] +pub(crate) fn get_tcp_user_timeout(fd: BorrowedFd<'_>) -> io::Result { + getsockopt(fd, c::IPPROTO_TCP, c::TCP_USER_TIMEOUT) +} + +#[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), + } +} + +#[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, + } +} + +#[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).s_addr, + imr_interface: to_imr_addr(interface).s_addr, + imr_sourceaddr: to_imr_addr(sourceaddr).s_addr, + } +} + +#[inline] +fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr { + c::in_addr { + s_addr: 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_ifindex: to_ipv6mr_interface(interface), + } +} + +#[inline] +fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr { + c::in6_addr { + in6_u: linux_raw_sys::net::in6_addr__bindgen_ty_1 { + u6_addr8: multiaddr.octets(), + }, + } +} + +#[inline] +fn to_ipv6mr_interface(interface: u32) -> c::c_int { + interface as c::c_int +} + +#[inline] +fn from_bool(value: bool) -> c::c_uint { + c::c_uint::from(value) +} + +#[inline] +fn to_bool(value: c::c_uint) -> bool { + value != 0 +} + +/// Convert to seconds, rounding up if necessary. +#[inline] +fn duration_to_secs>(duration: Duration) -> io::Result { + 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/src/backend/linux_raw/net/syscalls.rs b/src/backend/linux_raw/net/syscalls.rs index 24a035403..908cf773f 100644 --- a/src/backend/linux_raw/net/syscalls.rs +++ b/src/backend/linux_raw/net/syscalls.rs @@ -30,8 +30,8 @@ use { crate::backend::reg::{ArgReg, SocketArg}, linux_raw_sys::net::{ SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME, - SYS_GETSOCKOPT, SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMSG, - SYS_SENDTO, SYS_SETSOCKOPT, SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR, + SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMSG, SYS_SENDTO, + SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR, }, }; @@ -919,622 +919,3 @@ pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> { )) } } - -pub(crate) mod sockopt { - use super::{c, BorrowedFd}; - use crate::io; - use crate::net::sockopt::Timeout; - use crate::net::{AddressFamily, Ipv4Addr, Ipv6Addr, SocketType}; - use c::{SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD}; - use core::time::Duration; - use linux_raw_sys::general::{__kernel_old_timeval, __kernel_sock_timeval}; - use linux_raw_sys::net::{SO_ACCEPTCONN, TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL}; - - #[inline] - fn getsockopt(fd: BorrowedFd<'_>, level: u32, optname: u32) -> io::Result { - use super::*; - - let mut optlen = core::mem::size_of::(); - debug_assert!( - optlen as usize >= core::mem::size_of::(), - "Socket APIs don't ever use `bool` directly" - ); - - #[cfg(not(target_arch = "x86"))] - unsafe { - let mut value = MaybeUninit::::uninit(); - ret(syscall!( - __NR_getsockopt, - fd, - c_uint(level), - c_uint(optname), - &mut value, - by_mut(&mut optlen) - ))?; - - assert_eq!( - optlen as usize, - core::mem::size_of::(), - "unexpected getsockopt size" - ); - Ok(value.assume_init()) - } - #[cfg(target_arch = "x86")] - unsafe { - let mut value = MaybeUninit::::uninit(); - ret(syscall!( - __NR_socketcall, - x86_sys(SYS_GETSOCKOPT), - slice_just_addr::, _>(&[ - fd.into(), - c_uint(level), - c_uint(optname), - (&mut value).into(), - by_mut(&mut optlen), - ]) - ))?; - assert_eq!( - optlen as usize, - core::mem::size_of::(), - "unexpected getsockopt size" - ); - Ok(value.assume_init()) - } - } - - #[inline] - fn setsockopt( - fd: BorrowedFd<'_>, - level: u32, - optname: u32, - value: T, - ) -> io::Result<()> { - use super::*; - - let optlen = core::mem::size_of::().try_into().unwrap(); - debug_assert!( - optlen as usize >= core::mem::size_of::(), - "Socket APIs don't ever use `bool` directly" - ); - - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_setsockopt, - fd, - c_uint(level), - c_uint(optname), - by_ref(&value), - socklen_t(optlen) - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_SETSOCKOPT), - slice_just_addr::, _>(&[ - fd.into(), - c_uint(level), - c_uint(optname), - by_ref(&value), - socklen_t(optlen), - ]) - )) - } - } - - #[inline] - pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result { - 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 { - 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 { - getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool) - } - - #[inline] - pub(crate) fn set_socket_linger( - fd: BorrowedFd<'_>, - linger: Option, - ) -> 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: c::c_int::from(linger.is_some()), - l_linger, - }; - setsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER, linger) - } - - #[inline] - pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result> { - 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))) - } - - #[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)) - } - - #[inline] - pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result { - 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, - ) -> io::Result<()> { - let time = duration_to_linux_sock_timeval(timeout)?; - let optname = match id { - Timeout::Recv => SO_RCVTIMEO_NEW, - Timeout::Send => SO_SNDTIMEO_NEW, - }; - match setsockopt(fd, c::SOL_SOCKET, optname, time) { - Err(io::Errno::NOPROTOOPT) if SO_RCVTIMEO_NEW != SO_RCVTIMEO_OLD => { - set_socket_timeout_old(fd, id, timeout) - } - otherwise => otherwise, - } - } - - /// Same as `set_socket_timeout` but uses `__kernel_old_timeval` instead of - /// `__kernel_sock_timeval` and `_OLD` constants instead of `_NEW`. - fn set_socket_timeout_old( - fd: BorrowedFd<'_>, - id: Timeout, - timeout: Option, - ) -> io::Result<()> { - let time = duration_to_linux_old_timeval(timeout)?; - let optname = match id { - Timeout::Recv => SO_RCVTIMEO_OLD, - Timeout::Send => SO_SNDTIMEO_OLD, - }; - setsockopt(fd, c::SOL_SOCKET, optname, time) - } - - #[inline] - pub(crate) fn get_socket_timeout( - fd: BorrowedFd<'_>, - id: Timeout, - ) -> io::Result> { - let optname = match id { - Timeout::Recv => SO_RCVTIMEO_NEW, - Timeout::Send => SO_SNDTIMEO_NEW, - }; - let time: __kernel_sock_timeval = match getsockopt(fd, c::SOL_SOCKET, optname) { - Err(io::Errno::NOPROTOOPT) if SO_RCVTIMEO_NEW != SO_RCVTIMEO_OLD => { - return get_socket_timeout_old(fd, id) - } - otherwise => otherwise?, - }; - Ok(duration_from_linux_sock_timeval(time)) - } - - /// Same as `get_socket_timeout` but uses `__kernel_old_timeval` instead of - /// `__kernel_sock_timeval` and `_OLD` constants instead of `_NEW`. - fn get_socket_timeout_old(fd: BorrowedFd<'_>, id: Timeout) -> io::Result> { - let optname = match id { - Timeout::Recv => SO_RCVTIMEO_OLD, - Timeout::Send => SO_SNDTIMEO_OLD, - }; - let time: __kernel_old_timeval = getsockopt(fd, c::SOL_SOCKET, optname)?; - Ok(duration_from_linux_old_timeval(time)) - } - - /// Convert a `__linux_sock_timeval` to a Rust `Option`. - #[inline] - fn duration_from_linux_sock_timeval(time: __kernel_sock_timeval) -> Option { - if time.tv_sec == 0 && time.tv_usec == 0 { - None - } else { - Some( - Duration::from_secs(time.tv_sec as u64) - + Duration::from_micros(time.tv_usec as u64), - ) - } - } - - /// Like `duration_from_linux` but uses Linux's old 32-bit - /// `__kernel_old_timeval`. - fn duration_from_linux_old_timeval(time: __kernel_old_timeval) -> Option { - if time.tv_sec == 0 && time.tv_usec == 0 { - None - } else { - Some( - Duration::from_secs(time.tv_sec as u64) - + Duration::from_micros(time.tv_usec as u64), - ) - } - } - - /// Convert a Rust `Option` to a `__kernel_sock_timeval`. - #[inline] - fn duration_to_linux_sock_timeval( - timeout: Option, - ) -> io::Result<__kernel_sock_timeval> { - Ok(match timeout { - Some(timeout) => { - if timeout == Duration::ZERO { - return Err(io::Errno::INVAL); - } - // `subsec_micros` rounds down, so we use `subsec_nanos` and - // manually round up. - let mut timeout = __kernel_sock_timeval { - tv_sec: timeout.as_secs().try_into().unwrap_or(i64::MAX), - tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _, - }; - if timeout.tv_sec == 0 && timeout.tv_usec == 0 { - timeout.tv_usec = 1; - } - timeout - } - None => __kernel_sock_timeval { - tv_sec: 0, - tv_usec: 0, - }, - }) - } - - /// Like `duration_to_linux` but uses Linux's old 32-bit - /// `__kernel_old_timeval`. - fn duration_to_linux_old_timeval( - timeout: Option, - ) -> io::Result<__kernel_old_timeval> { - Ok(match timeout { - Some(timeout) => { - if timeout == Duration::ZERO { - return Err(io::Errno::INVAL); - } - - // `subsec_micros` rounds down, so we use `subsec_nanos` and - // manually round up. - let mut timeout = __kernel_old_timeval { - tv_sec: timeout.as_secs().try_into().unwrap_or(c::c_long::MAX), - tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _, - }; - if timeout.tv_sec == 0 && timeout.tv_usec == 0 { - timeout.tv_usec = 1; - } - timeout - } - None => __kernel_old_timeval { - tv_sec: 0, - tv_usec: 0, - }, - }) - } - - #[inline] - pub(crate) fn get_socket_error(fd: BorrowedFd<'_>) -> io::Result> { - 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 { - 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::OVERFLOW)?; - setsockopt(fd, c::SOL_SOCKET as _, c::SO_RCVBUF, size) - } - - #[inline] - pub(crate) fn get_socket_recv_buffer_size(fd: BorrowedFd<'_>) -> io::Result { - 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::OVERFLOW)?; - setsockopt(fd, c::SOL_SOCKET as _, c::SO_SNDBUF, size) - } - - #[inline] - pub(crate) fn get_socket_send_buffer_size(fd: BorrowedFd<'_>) -> io::Result { - getsockopt(fd, c::SOL_SOCKET as _, c::SO_SNDBUF).map(|size: u32| size as usize) - } - - #[inline] - pub(crate) fn get_socket_domain(fd: BorrowedFd<'_>) -> io::Result { - 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] - pub(crate) fn get_socket_acceptconn(fd: BorrowedFd<'_>) -> io::Result { - getsockopt(fd, c::SOL_SOCKET as _, 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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<()> { - let mreq = to_ipv6mr(multiaddr, interface); - setsockopt(fd, c::IPPROTO_IPV6 as _, c::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<()> { - let mreq = to_ipv6mr(multiaddr, interface); - setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_DROP_MEMBERSHIP, mreq) - } - - #[inline] - pub(crate) fn get_ipv6_unicast_hops(fd: BorrowedFd<'_>) -> io::Result { - 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) -> io::Result<()> { - let hops = match hops { - Some(hops) => hops.into(), - 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 { - getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool) - } - - #[inline] - pub(crate) fn set_tcp_keepcnt(fd: BorrowedFd<'_>, count: u32) -> io::Result<()> { - setsockopt(fd, c::IPPROTO_TCP as _, TCP_KEEPCNT, count) - } - - #[inline] - pub(crate) fn get_tcp_keepcnt(fd: BorrowedFd<'_>) -> io::Result { - getsockopt(fd, c::IPPROTO_TCP as _, TCP_KEEPCNT) - } - - #[inline] - 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] - pub(crate) fn get_tcp_keepidle(fd: BorrowedFd<'_>) -> io::Result { - let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP as _, TCP_KEEPIDLE)?; - Ok(Duration::from_secs(secs as u64)) - } - - #[inline] - 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 _, TCP_KEEPINTVL, secs) - } - - #[inline] - pub(crate) fn get_tcp_keepintvl(fd: BorrowedFd<'_>) -> io::Result { - let secs: c::c_uint = getsockopt(fd, c::IPPROTO_TCP as _, 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 { - c::in_addr { - s_addr: 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_ifindex: to_ipv6mr_interface(interface), - } - } - - #[inline] - fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr { - c::in6_addr { - in6_u: linux_raw_sys::net::in6_addr__bindgen_ty_1 { - u6_addr8: multiaddr.octets(), - }, - } - } - - #[inline] - fn to_ipv6mr_interface(interface: u32) -> c::c_int { - interface as c::c_int - } - - #[inline] - fn from_bool(value: bool) -> c::c_uint { - c::c_uint::from(value) - } - - #[inline] - fn to_bool(value: c::c_uint) -> bool { - value != 0 - } - - /// Convert to seconds, rounding up if necessary. - #[inline] - fn duration_to_secs>(duration: Duration) -> io::Result { - 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/src/net/sockopt.rs b/src/net/sockopt.rs index 1939155d9..ea736c2af 100644 --- a/src/net/sockopt.rs +++ b/src/net/sockopt.rs @@ -2,6 +2,143 @@ //! //! In the rustix API, there is a separate function for each option, so that //! it can be given an option-specific type signature. +//! +//! # References for all `get_*` functions: +//! +//! - [POSIX `getsockopt`] +//! - [Linux `getsockopt`] +//! - [Winsock2 `getsockopt`] +//! - [Apple `getsockopt`] +//! - [FreeBSD `getsockopt`] +//! - [NetBSD `getsockopt`] +//! - [OpenBSD `getsockopt`] +//! - [DragonFly BSD `getsockopt`] +//! - [illumos `getsockopt`] +//! - [glibc `getsockopt`] +//! +//! [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html +//! [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html +//! [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt +//! [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html +//! [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 +//! [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 +//! [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 +//! [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 +//! [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt +//! [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html +//! +//! # References for all `set_*` functions: +//! +//! - [POSIX `setsockopt`] +//! - [Linux `setsockopt`] +//! - [Winsock2 `setsockopt`] +//! - [Apple `setsockopt`] +//! - [FreeBSD `setsockopt`] +//! - [NetBSD `setsockopt`] +//! - [OpenBSD `setsockopt`] +//! - [DragonFly BSD `setsockopt`] +//! - [illumos `setsockopt`] +//! - [glibc `setsockopt`] +//! +//! [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html +//! [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html +//! [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt +//! [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html +//! [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 +//! [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 +//! [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 +//! [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 +//! [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt +//! [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html +//! +//! # References for `get_socket_*` and `set_socket_*` functions: +//! +//! - [References for all `get_*` functions] +//! - [References for all `set_*` functions] +//! - [POSIX `sys/socket.h`] +//! - [Linux `socket`] +//! - [Winsock2 `SOL_SOCKET` options] +//! - [glibc `SOL_SOCKET` Options] +//! +//! [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html +//! [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html +//! [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options +//! [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +//! +//! # References for `get_ip_*` and `set_ip_*` functions: +//! +//! - [References for all `get_*` functions] +//! - [References for all `set_*` functions] +//! - [POSIX `netinet/in.h`] +//! - [Linux `ip`] +//! - [Winsock2 `IPPROTO_IP` options] +//! - [Apple `ip`] +//! - [FreeBSD `ip`] +//! - [NetBSD `ip`] +//! - [OpenBSD `ip`] +//! - [DragonFly BSD `ip`] +//! - [illumos `ip`] +//! +//! [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html +//! [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html +//! [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options +//! [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html +//! [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 +//! [NetBSD `ip`]: https://man.netbsd.org/ip.4 +//! [OpenBSD `ip`]: https://man.openbsd.org/ip.4 +//! [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 +//! [illumos `ip`]: https://illumos.org/man/4P/ip +//! +//! # References for `get_ipv6_*` and `set_ipv6_*` functions: +//! +//! - [References for all `get_*` functions] +//! - [References for all `set_*` functions] +//! - [POSIX `netinet/in.h`] +//! - [Linux `ipv6`] +//! - [Winsock2 `IPPROTO_IPV6` options] +//! - [Apple `ip6`] +//! - [FreeBSD `ip6`] +//! - [NetBSD `ip6`] +//! - [OpenBSD `ip6`] +//! - [DragonFly BSD `ip6`] +//! - [illumos `ip6`] +//! +//! [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html +//! [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html +//! [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options +//! [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html +//! [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 +//! [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 +//! [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 +//! [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 +//! [illumos `ip6`]: https://illumos.org/man/4P/ip6 +//! +//! # References for `get_tcp_*` and `set_tcp_*` functions: +//! +//! - [References for all `get_*` functions] +//! - [References for all `set_*` functions] +//! - [POSIX `netinet/tcp.h`] +//! - [Linux `tcp`] +//! - [Winsock2 `IPPROTO_TCP` options] +//! - [Apple `tcp`] +//! - [FreeBSD `tcp`] +//! - [NetBSD `tcp`] +//! - [OpenBSD `tcp`] +//! - [DragonFly BSD `tcp`] +//! - [illumos `tcp`] +//! +//! [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html +//! [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html +//! [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options +//! [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html +//! [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 +//! [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 +//! [OpenBSD `tcp`]: https://man.openbsd.org/tcp.4 +//! [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 +//! [illumos `tcp`]: https://illumos.org/man/4P/tcp +//! +//! [References for all `get_*` functions]: #references-for-all-get_-functions +//! [References for all `set_*` functions]: #references-for-all-set_-functions #![doc(alias = "getsockopt")] #![doc(alias = "setsockopt")] @@ -26,9 +163,6 @@ use core::time::Duration; /// Timeout identifier for use with [`set_socket_timeout`] and /// [`get_socket_timeout`]. -/// -/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout. -/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] #[repr(u32)] pub enum Timeout { @@ -41,333 +175,112 @@ pub enum Timeout { /// `getsockopt(fd, SOL_SOCKET, SO_TYPE)`—Returns the type of a socket. /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_TYPE")] pub fn get_socket_type(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_type(fd.as_fd()) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, value)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html + backend::net::sockopt::get_socket_type(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, value)`—Set whether local +/// addresses may be reused in `bind`. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_REUSEADDR")] pub fn set_socket_reuseaddr(fd: Fd, value: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_reuseaddr(fd.as_fd(), value) + backend::net::sockopt::set_socket_reuseaddr(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_REUSEADDR)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_REUSEADDR")] pub fn get_socket_reuseaddr(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_reuseaddr(fd.as_fd()) + backend::net::sockopt::get_socket_reuseaddr(fd.as_fd()) } /// `setsockopt(fd, SOL_SOCKET, SO_BROADCAST, broadcast)` /// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_BROADCAST")] -pub fn set_socket_broadcast(fd: Fd, broadcast: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_broadcast(fd.as_fd(), broadcast) +pub fn set_socket_broadcast(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_socket_broadcast(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_BROADCAST)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_BROADCAST")] pub fn get_socket_broadcast(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_broadcast(fd.as_fd()) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_LINGER, linger)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html + backend::net::sockopt::get_socket_broadcast(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_LINGER, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_LINGER")] -pub fn set_socket_linger(fd: Fd, linger: Option) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_linger(fd.as_fd(), linger) +pub fn set_socket_linger(fd: Fd, value: Option) -> io::Result<()> { + backend::net::sockopt::set_socket_linger(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_LINGER)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_LINGER")] pub fn get_socket_linger(fd: Fd) -> io::Result> { - backend::net::syscalls::sockopt::get_socket_linger(fd.as_fd()) + backend::net::sockopt::get_socket_linger(fd.as_fd()) } -/// `setsockopt(fd, SOL_SOCKET, SO_PASSCRED, passcred)` +/// `setsockopt(fd, SOL_SOCKET, SO_PASSCRED, value)` /// -/// # References -/// - [Linux `setsockopt`] -/// - [Linux `socket`] +/// See the [module-level documentation] for more. /// -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(linux_kernel)] #[inline] #[doc(alias = "SO_PASSCRED")] -pub fn set_socket_passcred(fd: Fd, passcred: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_passcred(fd.as_fd(), passcred) +pub fn set_socket_passcred(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_socket_passcred(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_PASSCRED)` /// -/// # References -/// - [Linux `getsockopt`] -/// - [Linux `socket`] +/// See the [module-level documentation] for more. /// -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(linux_kernel)] #[inline] #[doc(alias = "SO_PASSCRED")] pub fn get_socket_passcred(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_passcred(fd.as_fd()) + backend::net::sockopt::get_socket_passcred(fd.as_fd()) } /// `setsockopt(fd, SOL_SOCKET, id, timeout)`—Set the sending or receiving /// timeout. /// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_RCVTIMEO")] #[doc(alias = "SO_SNDTIMEO")] @@ -376,424 +289,127 @@ pub fn set_socket_timeout( id: Timeout, timeout: Option, ) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_timeout(fd.as_fd(), id, timeout) + backend::net::sockopt::set_socket_timeout(fd.as_fd(), id, timeout) } /// `getsockopt(fd, SOL_SOCKET, id)`—Get the sending or receiving timeout. /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_RCVTIMEO")] #[doc(alias = "SO_SNDTIMEO")] pub fn get_socket_timeout(fd: Fd, id: Timeout) -> io::Result> { - backend::net::syscalls::sockopt::get_socket_timeout(fd.as_fd(), id) + backend::net::sockopt::get_socket_timeout(fd.as_fd(), id) } /// `getsockopt(fd, SOL_SOCKET, SO_ERROR)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_ERROR")] pub fn get_socket_error(fd: Fd) -> io::Result> { - backend::net::syscalls::sockopt::get_socket_error(fd.as_fd()) + backend::net::sockopt::get_socket_error(fd.as_fd()) } /// `getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(any(apple, target_os = "freebsd"))] #[doc(alias = "SO_NOSIGPIPE")] #[inline] pub fn get_socket_nosigpipe(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_nosigpipe(fd.as_fd()) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, val)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html + backend::net::sockopt::get_socket_nosigpipe(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(any(apple, target_os = "freebsd"))] #[doc(alias = "SO_NOSIGPIPE")] #[inline] -pub fn set_socket_nosigpipe(fd: Fd, val: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_nosigpipe(fd.as_fd(), val) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, keepalive)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +pub fn set_socket_nosigpipe(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_socket_nosigpipe(fd.as_fd(), value) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_KEEPALIVE")] -pub fn set_socket_keepalive(fd: Fd, keepalive: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_keepalive(fd.as_fd(), keepalive) +pub fn set_socket_keepalive(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_socket_keepalive(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_KEEPALIVE")] pub fn get_socket_keepalive(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_keepalive(fd.as_fd()) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_RCVBUF, size)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html + backend::net::sockopt::get_socket_keepalive(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_RCVBUF, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_RCVBUF")] -pub fn set_socket_recv_buffer_size(fd: Fd, size: usize) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_recv_buffer_size(fd.as_fd(), size) +pub fn set_socket_recv_buffer_size(fd: Fd, value: usize) -> io::Result<()> { + backend::net::sockopt::set_socket_recv_buffer_size(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_RCVBUF)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_RCVBUF")] pub fn get_socket_recv_buffer_size(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_recv_buffer_size(fd.as_fd()) -} - -/// `setsockopt(fd, SOL_SOCKET, SO_SNDBUF, size)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `setsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `setsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/setsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/setsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/setsockopt -/// [glibc `setsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html + backend::net::sockopt::get_socket_recv_buffer_size(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_SNDBUF, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_SNDBUF")] -pub fn set_socket_send_buffer_size(fd: Fd, size: usize) -> io::Result<()> { - backend::net::syscalls::sockopt::set_socket_send_buffer_size(fd.as_fd(), size) +pub fn set_socket_send_buffer_size(fd: Fd, value: usize) -> io::Result<()> { + backend::net::sockopt::set_socket_send_buffer_size(fd.as_fd(), value) } /// `getsockopt(fd, SOL_SOCKET, SO_SNDBUF)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "SO_SNDBUF")] pub fn get_socket_send_buffer_size(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_send_buffer_size(fd.as_fd()) + backend::net::sockopt::get_socket_send_buffer_size(fd.as_fd()) } /// `getsockopt(fd, SOL_SOCKET, SO_DOMAIN)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(not(any( apple, windows, @@ -808,705 +424,205 @@ pub fn get_socket_send_buffer_size(fd: Fd) -> io::Result { #[inline] #[doc(alias = "SO_DOMAIN")] pub fn get_socket_domain(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_domain(fd.as_fd()) + backend::net::sockopt::get_socket_domain(fd.as_fd()) } /// `getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `sys/socket.h`] -/// - [Linux `getsockopt`] -/// - [Linux `socket`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `SOL_SOCKET` options] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc `getsockopt`] -/// - [glibc `SOL_SOCKET` Options] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `sys/socket.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `SOL_SOCKET` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [NetBSD]: https://man.netbsd.org/getsockopt.2 -/// [OpenBSD]: https://man.openbsd.org/getsockopt.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/getsockopt -/// [glibc `getsockopt`]: https://www.gnu.org/software/libc/manual/html_node/Socket-Option-Functions.html -/// [glibc `SOL_SOCKET` options]: https://www.gnu.org/software/libc/manual/html_node/Socket_002dLevel-Options.html +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[cfg(not(apple))] // Apple platforms declare the constant, but do not actually implement it. #[inline] #[doc(alias = "SO_ACCEPTCONN")] pub fn get_socket_acceptconn(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_socket_acceptconn(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IP, IP_TTL, ttl)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `setsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip + backend::net::sockopt::get_socket_acceptconn(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[inline] +#[doc(alias = "SO_OOBINLINE")] +pub fn set_socket_oobinline(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_socket_oobinline(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_OOBINLINE)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[inline] +#[doc(alias = "SO_OOBINLINE")] +pub fn get_socket_oobinline(fd: Fd) -> io::Result { + backend::net::sockopt::get_socket_oobinline(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_TTL, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions #[inline] #[doc(alias = "IP_TTL")] -pub fn set_ip_ttl(fd: Fd, ttl: u32) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ip_ttl(fd.as_fd(), ttl) +pub fn set_ip_ttl(fd: Fd, value: u32) -> io::Result<()> { + backend::net::sockopt::set_ip_ttl(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IP, IP_TTL)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `getsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_TTL")] pub fn get_ip_ttl(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ip_ttl(fd.as_fd()) + backend::net::sockopt::get_ip_ttl(fd.as_fd()) } /// `setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, only_v6)` /// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_V6ONLY")] -pub fn set_ipv6_v6only(fd: Fd, only_v6: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_v6only(fd.as_fd(), only_v6) +pub fn set_ipv6_v6only(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_ipv6_v6only(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `getsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_V6ONLY")] pub fn get_ipv6_v6only(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ipv6_v6only(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, multicast_loop)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `setsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip + backend::net::sockopt::get_ipv6_v6only(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_MULTICAST_LOOP")] -pub fn set_ip_multicast_loop(fd: Fd, multicast_loop: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ip_multicast_loop(fd.as_fd(), multicast_loop) +pub fn set_ip_multicast_loop(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_ip_multicast_loop(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `getsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_MULTICAST_LOOP")] pub fn get_ip_multicast_loop(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ip_multicast_loop(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, multicast_ttl)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `setsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip + backend::net::sockopt::get_ip_multicast_loop(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_MULTICAST_TTL")] -pub fn set_ip_multicast_ttl(fd: Fd, multicast_ttl: u32) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ip_multicast_ttl(fd.as_fd(), multicast_ttl) +pub fn set_ip_multicast_ttl(fd: Fd, value: u32) -> io::Result<()> { + backend::net::sockopt::set_ip_multicast_ttl(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `getsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_MULTICAST_TTL")] pub fn get_ip_multicast_ttl(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ip_multicast_ttl(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, multicast_loop)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 + backend::net::sockopt::get_ip_multicast_ttl(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_MULTICAST_LOOP")] -pub fn set_ipv6_multicast_loop(fd: Fd, multicast_loop: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_multicast_loop(fd.as_fd(), multicast_loop) +pub fn set_ipv6_multicast_loop(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_ipv6_multicast_loop(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `getsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_MULTICAST_LOOP")] pub fn get_ipv6_multicast_loop(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ipv6_multicast_loop(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, multicast_hops)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 -#[inline] -#[doc(alias = "IP_MULTICAST_TTL")] -pub fn set_ipv6_multicast_hops(fd: Fd, multicast_hops: u32) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_multicast_hops(fd.as_fd(), multicast_hops) + backend::net::sockopt::get_ipv6_multicast_loop(fd.as_fd()) } /// `getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `getsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_UNICAST_HOPS")] pub fn get_ipv6_unicast_hops(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ipv6_unicast_hops(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, unicast_hops)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 + backend::net::sockopt::get_ipv6_unicast_hops(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_UNICAST_HOPS")] -pub fn set_ipv6_unicast_hops(fd: Fd, unicast_hops: Option) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_unicast_hops(fd.as_fd(), unicast_hops) +pub fn set_ipv6_unicast_hops(fd: Fd, value: Option) -> io::Result<()> { + backend::net::sockopt::set_ipv6_unicast_hops(fd.as_fd(), value) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[inline] +#[doc(alias = "IPV6_MULTICAST_HOPS")] +pub fn set_ipv6_multicast_hops(fd: Fd, value: u32) -> io::Result<()> { + backend::net::sockopt::set_ipv6_multicast_hops(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `getsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `getsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `getsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] -#[doc(alias = "IP_MULTICAST_TTL")] +#[doc(alias = "IPV6_MULTICAST_HOPS")] pub fn get_ipv6_multicast_hops(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_ipv6_multicast_hops(fd.as_fd()) + backend::net::sockopt::get_ipv6_multicast_hops(fd.as_fd()) } /// `setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, multiaddr, interface)` /// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `setsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip +/// This is similar to [`set_ip_add_membership`] but always sets `ifindex` value +/// to zero. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_ADD_MEMBERSHIP")] pub fn set_ip_add_membership( @@ -1514,51 +630,89 @@ pub fn set_ip_add_membership( multiaddr: &Ipv4Addr, interface: &Ipv4Addr, ) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ip_add_membership(fd.as_fd(), multiaddr, interface) + backend::net::sockopt::set_ip_add_membership(fd.as_fd(), multiaddr, interface) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, multiaddr, address, ifindex)` +/// +/// This is similar to [`set_ip_add_membership_with_ifindex`] but additionally +/// allows a `ifindex` value to be given. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any( + apple, + freebsdlike, + linux_like, + target_os = "fuchsia", + target_os = "openbsd" +))] +#[inline] +#[doc(alias = "IP_ADD_MEMBERSHIP")] +pub fn set_ip_add_membership_with_ifindex( + fd: Fd, + multiaddr: &Ipv4Addr, + address: &Ipv4Addr, + ifindex: i32, +) -> io::Result<()> { + backend::net::sockopt::set_ip_add_membership_with_ifindex( + fd.as_fd(), + multiaddr, + address, + ifindex, + ) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any(apple, freebsdlike, linux_like, solarish, target_os = "aix"))] +#[inline] +#[doc(alias = "IP_ADD_SOURCE_MEMBERSHIP")] +pub fn set_ip_add_source_membership( + fd: Fd, + multiaddr: &Ipv4Addr, + interface: &Ipv4Addr, + sourceaddr: &Ipv4Addr, +) -> io::Result<()> { + backend::net::sockopt::set_ip_add_source_membership( + fd.as_fd(), + multiaddr, + interface, + sourceaddr, + ) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any(apple, freebsdlike, linux_like, solarish, target_os = "aix"))] +#[inline] +#[doc(alias = "IP_DROP_SOURCE_MEMBERSHIP")] +pub fn set_ip_drop_source_membership( + fd: Fd, + multiaddr: &Ipv4Addr, + interface: &Ipv4Addr, + sourceaddr: &Ipv4Addr, +) -> io::Result<()> { + backend::net::sockopt::set_ip_drop_source_membership( + fd.as_fd(), + multiaddr, + interface, + sourceaddr, + ) } /// `setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, multiaddr, interface)` /// -/// `IPV6_ADD_MEMBERSHIP` is the same as `IPV6_JOIN_GROUP` in POSIX. -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_JOIN_GROUP")] #[doc(alias = "IPV6_ADD_MEMBERSHIP")] @@ -1567,49 +721,17 @@ pub fn set_ipv6_add_membership( multiaddr: &Ipv6Addr, interface: u32, ) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_add_membership(fd.as_fd(), multiaddr, interface) + backend::net::sockopt::set_ipv6_add_membership(fd.as_fd(), multiaddr, interface) } /// `setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, multiaddr, interface)` /// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ip`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IP` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip`] -/// - [illumos `setsockopt`] -/// - [illumos `ip`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ip`]: https://man7.org/linux/man-pages/man7/ip.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip`]: https://man.freebsd.org/cgi/man.cgi?query=ip&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip`]: https://man.netbsd.org/ip.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip`]: https://man.openbsd.org/ip.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip`]: https://man.dragonflybsd.org/?command=ip§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip`]: https://illumos.org/man/4P/ip +/// This is similar to [`set_ip_drop_membership`] but always sets `ifindex` value +/// to zero. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions #[inline] #[doc(alias = "IP_DROP_MEMBERSHIP")] pub fn set_ip_drop_membership( @@ -1617,51 +739,45 @@ pub fn set_ip_drop_membership( multiaddr: &Ipv4Addr, interface: &Ipv4Addr, ) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ip_drop_membership(fd.as_fd(), multiaddr, interface) + backend::net::sockopt::set_ip_drop_membership(fd.as_fd(), multiaddr, interface) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, multiaddr, interface)` +/// +/// This is similar to [`set_ip_drop_membership_with_ifindex`] but additionally +/// allows a `ifindex` value to be given. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any( + apple, + freebsdlike, + linux_like, + target_os = "fuchsia", + target_os = "openbsd" +))] +#[inline] +#[doc(alias = "IP_DROP_MEMBERSHIP")] +pub fn set_ip_drop_membership_with_ifindex( + fd: Fd, + multiaddr: &Ipv4Addr, + address: &Ipv4Addr, + ifindex: i32, +) -> io::Result<()> { + backend::net::sockopt::set_ip_drop_membership_with_ifindex( + fd.as_fd(), + multiaddr, + address, + ifindex, + ) } /// `setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, multiaddr, interface)` /// -/// `IPV6_DROP_MEMBERSHIP` is the same as `IPV6_LEAVE_GROUP` in POSIX. -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/in.h`] -/// - [Linux `setsockopt`] -/// - [Linux `ipv6`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_IPV6` options] -/// - [Apple `setsockopt`] -/// - [Apple `ip6`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `ip6`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `ip6`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `ip6`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `ip6`] -/// - [illumos `setsockopt`] -/// - [illumos `ip6`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/in.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `ipv6`]: https://man7.org/linux/man-pages/man7/ipv6.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_IPV6` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `ip6`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/ip6.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `ip6`]: https://man.freebsd.org/cgi/man.cgi?query=ip6&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `ip6`]: https://man.netbsd.org/ip6.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `ip6`]: https://man.openbsd.org/ip6.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `ip6`]: https://man.dragonflybsd.org/?command=ip6§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `ip6`]: https://illumos.org/man/4P/ip6 +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions #[inline] #[doc(alias = "IPV6_LEAVE_GROUP")] #[doc(alias = "IPV6_DROP_MEMBERSHIP")] @@ -1670,361 +786,229 @@ pub fn set_ipv6_drop_membership( multiaddr: &Ipv6Addr, interface: u32, ) -> io::Result<()> { - backend::net::syscalls::sockopt::set_ipv6_drop_membership(fd.as_fd(), multiaddr, interface) -} - -/// `setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, nodelay)` -/// -/// # References -/// - [POSIX `setsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `setsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `setsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `setsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `setsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `setsockopt`] -/// - [NetBSD `tcp`] -/// - [OpenBSD `setsockopt`] -/// - [OpenBSD `tcp`] -/// - [DragonFly BSD `setsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `setsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `setsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `setsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `setsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `setsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `setsockopt`]: https://man.netbsd.org/setsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [OpenBSD `setsockopt`]: https://man.openbsd.org/setsockopt.2 -/// [OpenBSD `tcp`]: https://man.openbsd.org/tcp.4 -/// [DragonFly BSD `setsockopt`]: https://man.dragonflybsd.org/?command=setsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `setsockopt`]: https://illumos.org/man/3SOCKET/setsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp + backend::net::sockopt::set_ipv6_drop_membership(fd.as_fd(), multiaddr, interface) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_TOS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "haiku", + target_os = "nto", + target_env = "newlib" +))] +#[inline] +#[doc(alias = "IP_TOS")] +pub fn set_ip_tos(fd: Fd, value: u8) -> io::Result<()> { + backend::net::sockopt::set_ip_tos(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_TOS)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "haiku", + target_os = "nto", + target_env = "newlib" +))] +#[inline] +#[doc(alias = "IP_TOS")] +pub fn get_ip_tos(fd: Fd) -> io::Result { + backend::net::sockopt::get_ip_tos(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_RECVTOS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +#[inline] +#[doc(alias = "IP_RECVTOS")] +pub fn set_ip_recvtos(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_ip_recvtos(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_RECVTOS)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ip_-and-set_ip_-functions +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +#[inline] +#[doc(alias = "IP_RECVTOS")] +pub fn get_ip_recvtos(fd: Fd) -> io::Result { + backend::net::sockopt::get_ip_recvtos(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_RECVTCLASS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "nto" +))] +#[inline] +#[doc(alias = "IPV6_RECVTCLASS")] +pub fn set_ipv6_recvtclass(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_ipv6_recvtclass(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_RECVTCLASS)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "nto" +))] +#[inline] +#[doc(alias = "IPV6_RECVTCLASS")] +pub fn get_ipv6_recvtclass(fd: Fd) -> io::Result { + backend::net::sockopt::get_ipv6_recvtclass(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[doc(alias = "TCP_NODELAY")] -pub fn set_tcp_nodelay(fd: Fd, nodelay: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::set_tcp_nodelay(fd.as_fd(), nodelay) +pub fn set_tcp_nodelay(fd: Fd, value: bool) -> io::Result<()> { + backend::net::sockopt::set_tcp_nodelay(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_TCP, TCP_NODELAY)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [OpenBSD `getsockopt`] -/// - [OpenBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [OpenBSD `getsockopt`]: https://man.openbsd.org/getsockopt.2 -/// [OpenBSD `tcp`]: https://man.openbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[doc(alias = "TCP_NODELAY")] pub fn get_tcp_nodelay(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_tcp_nodelay(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, count)` -/// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp + backend::net::sockopt::get_tcp_nodelay(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPCNT")] -pub fn set_tcp_keepcnt(fd: Fd, count: u32) -> io::Result<()> { - backend::net::syscalls::sockopt::set_tcp_keepcnt(fd.as_fd(), count) +pub fn set_tcp_keepcnt(fd: Fd, value: u32) -> io::Result<()> { + backend::net::sockopt::set_tcp_keepcnt(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPCNT")] pub fn get_tcp_keepcnt(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_tcp_keepcnt(fd.as_fd()) + backend::net::sockopt::get_tcp_keepcnt(fd.as_fd()) } -/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, duration)` +/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, value)` /// /// `TCP_KEEPALIVE` on Apple platforms. /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPIDLE")] -pub fn set_tcp_keepidle(fd: Fd, duration: Duration) -> io::Result<()> { - backend::net::syscalls::sockopt::set_tcp_keepidle(fd.as_fd(), duration) +pub fn set_tcp_keepidle(fd: Fd, value: Duration) -> io::Result<()> { + backend::net::sockopt::set_tcp_keepidle(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE)` /// /// `TCP_KEEPALIVE` on Apple platforms. /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPIDLE")] pub fn get_tcp_keepidle(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_tcp_keepidle(fd.as_fd()) -} - -/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, duration)` -/// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp + backend::net::sockopt::get_tcp_keepidle(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPINTVL")] -pub fn set_tcp_keepintvl(fd: Fd, duration: Duration) -> io::Result<()> { - backend::net::syscalls::sockopt::set_tcp_keepintvl(fd.as_fd(), duration) +pub fn set_tcp_keepintvl(fd: Fd, value: Duration) -> io::Result<()> { + backend::net::sockopt::set_tcp_keepintvl(fd.as_fd(), value) } /// `getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL)` /// -/// # References -/// - [POSIX `getsockopt`] -/// - [POSIX `netinet/tcp.h`] -/// - [Linux `getsockopt`] -/// - [Linux `tcp`] -/// - [Winsock2 `getsockopt`] -/// - [Winsock2 `IPPROTO_TCP` options] -/// - [Apple `getsockopt`] -/// - [Apple `tcp`] -/// - [FreeBSD `getsockopt`] -/// - [FreeBSD `tcp`] -/// - [NetBSD `getsockopt`] -/// - [NetBSD `tcp`] -/// - [DragonFly BSD `getsockopt`] -/// - [DragonFly BSD `tcp`] -/// - [illumos `getsockopt`] -/// - [illumos `tcp`] -/// -/// [POSIX `getsockopt`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html -/// [POSIX `netinet/tcp.h`]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html -/// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html -/// [Linux `tcp`]: https://man7.org/linux/man-pages/man7/tcp.7.html -/// [Winsock2 `getsockopt`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt -/// [Winsock2 `IPPROTO_TCP` options]: https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options -/// [Apple `getsockopt`]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html -/// [Apple `tcp`]: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/man/man4/tcp.4.auto.html -/// [FreeBSD `getsockopt`]: https://man.freebsd.org/cgi/man.cgi?query=getsockopt&sektion=2 -/// [FreeBSD `tcp`]: https://man.freebsd.org/cgi/man.cgi?query=tcp&sektion=4 -/// [NetBSD `getsockopt`]: https://man.netbsd.org/getsockopt.2 -/// [NetBSD `tcp`]: https://man.netbsd.org/tcp.4 -/// [DragonFly BSD `getsockopt`]: https://man.dragonflybsd.org/?command=getsockopt§ion=2 -/// [DragonFly BSD `tcp`]: https://man.dragonflybsd.org/?command=tcp§ion=4 -/// [illumos `getsockopt`]: https://illumos.org/man/3SOCKET/getsockopt -/// [illumos `tcp`]: https://illumos.org/man/4P/tcp +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions #[inline] #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] #[doc(alias = "TCP_KEEPINTVL")] pub fn get_tcp_keepintvl(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::get_tcp_keepintvl(fd.as_fd()) + backend::net::sockopt::get_tcp_keepintvl(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[inline] +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[doc(alias = "TCP_USER_TIMEOUT")] +pub fn set_tcp_user_timeout(fd: Fd, value: u32) -> io::Result<()> { + backend::net::sockopt::set_tcp_user_timeout(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[inline] +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[doc(alias = "TCP_USER_TIMEOUT")] +pub fn get_tcp_user_timeout(fd: Fd) -> io::Result { + backend::net::sockopt::get_tcp_user_timeout(fd.as_fd()) } #[test] diff --git a/tests/net/sockopt.rs b/tests/net/sockopt.rs index b85babde0..69b7be6aa 100644 --- a/tests/net/sockopt.rs +++ b/tests/net/sockopt.rs @@ -1,84 +1,39 @@ -#[test] -fn test_sockopts_ipv4() { - use rustix::net::{AddressFamily, SocketType}; - use std::time::Duration; - - let s = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); +use rustix::fd::OwnedFd; +use rustix::net::sockopt; +use rustix::net::{AddressFamily, SocketType}; +use std::time::Duration; +// Test `socket` socket options. +fn test_sockopts_socket(s: &OwnedFd) { // On a new socket we shouldn't have a timeout yet. - assert!( - rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv) - .unwrap() - .is_none() - ); - assert_eq!( - rustix::net::sockopt::get_socket_type(&s).unwrap(), - SocketType::STREAM - ); - assert!(!rustix::net::sockopt::get_socket_reuseaddr(&s).unwrap()); - #[cfg(not(windows))] - assert!(!rustix::net::sockopt::get_socket_broadcast(&s).unwrap()); - // On a new socket we shouldn't have a linger yet. - assert!(rustix::net::sockopt::get_socket_linger(&s) + assert!(sockopt::get_socket_timeout(&s, sockopt::Timeout::Recv) .unwrap() .is_none()); + assert_eq!(sockopt::get_socket_type(&s).unwrap(), SocketType::STREAM); + assert!(!sockopt::get_socket_reuseaddr(&s).unwrap()); + #[cfg(not(windows))] + assert!(!sockopt::get_socket_broadcast(&s).unwrap()); + // On a new socket we shouldn't have a linger yet. + assert!(sockopt::get_socket_linger(&s).unwrap().is_none()); #[cfg(linux_kernel)] - assert!(!rustix::net::sockopt::get_socket_passcred(&s).unwrap()); - assert_ne!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 0); - assert_ne!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 77); - #[cfg(not(any(bsd, windows, target_os = "illumos")))] - assert!(rustix::net::sockopt::get_ip_multicast_loop(&s).unwrap()); - #[cfg(not(any(bsd, windows, target_os = "illumos")))] - assert_eq!(rustix::net::sockopt::get_ip_multicast_ttl(&s).unwrap(), 1); - assert!(!rustix::net::sockopt::get_tcp_nodelay(&s).unwrap()); + assert!(!sockopt::get_socket_passcred(&s).unwrap()); - #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] - { - assert!(rustix::net::sockopt::get_tcp_keepcnt(&s).is_ok()); - assert!(rustix::net::sockopt::get_tcp_keepidle(&s).is_ok()); - assert!(rustix::net::sockopt::get_tcp_keepintvl(&s).is_ok()); - } // On a new socket we shouldn't have an error yet. - assert_eq!(rustix::net::sockopt::get_socket_error(&s).unwrap(), Ok(())); - assert!(!rustix::net::sockopt::get_socket_keepalive(&s).unwrap()); - assert_ne!( - rustix::net::sockopt::get_socket_recv_buffer_size(&s).unwrap(), - 0 - ); - assert_ne!( - rustix::net::sockopt::get_socket_send_buffer_size(&s).unwrap(), - 0 - ); - #[cfg(not(any( - apple, - windows, - target_os = "dragonfly", - target_os = "emscripten", - target_os = "espidf", - target_os = "haiku", - target_os = "netbsd", - target_os = "nto", - )))] - assert_eq!( - rustix::net::sockopt::get_socket_domain(&s).unwrap(), - AddressFamily::INET - ); + assert_eq!(sockopt::get_socket_error(&s).unwrap(), Ok(())); + assert!(!sockopt::get_socket_keepalive(&s).unwrap()); + assert_ne!(sockopt::get_socket_recv_buffer_size(&s).unwrap(), 0); + assert_ne!(sockopt::get_socket_send_buffer_size(&s).unwrap(), 0); #[cfg(not(apple))] - assert!(!rustix::net::sockopt::get_socket_acceptconn(&s).unwrap()); + assert!(!sockopt::get_socket_acceptconn(&s).unwrap()); // Set a timeout. - rustix::net::sockopt::set_socket_timeout( - &s, - rustix::net::sockopt::Timeout::Recv, - Some(Duration::new(1, 1)), - ) - .unwrap(); + sockopt::set_socket_timeout(&s, sockopt::Timeout::Recv, Some(Duration::new(1, 1))).unwrap(); // Check that we have a timeout of at least the time we set. if cfg!(not(any(target_os = "freebsd", target_os = "netbsd"))) { assert!( - rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv) + sockopt::get_socket_timeout(&s, sockopt::Timeout::Recv) .unwrap() .unwrap() >= Duration::new(1, 1) @@ -86,7 +41,7 @@ fn test_sockopts_ipv4() { } else { // On FreeBSD <= 12 and NetBSD, it appears the system rounds the timeout down. assert!( - rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv) + sockopt::get_socket_timeout(&s, sockopt::Timeout::Recv) .unwrap() .unwrap() >= Duration::new(1, 0) @@ -94,139 +49,228 @@ fn test_sockopts_ipv4() { } // Set a timeout with more than a million nanoseconds. - rustix::net::sockopt::set_socket_timeout( - &s, - rustix::net::sockopt::Timeout::Recv, - Some(Duration::new(1, 10000000)), - ) - .unwrap(); + sockopt::set_socket_timeout(&s, sockopt::Timeout::Recv, Some(Duration::new(1, 10000000))) + .unwrap(); // Check that we have a timeout of at least the time we set. assert!( - rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv) + sockopt::get_socket_timeout(&s, sockopt::Timeout::Recv) .unwrap() .unwrap() >= Duration::new(1, 10000000) ); // Set the reuse address flag - rustix::net::sockopt::set_socket_reuseaddr(&s, true).unwrap(); + sockopt::set_socket_reuseaddr(&s, true).unwrap(); // Check that the reuse address flag is set. - assert!(rustix::net::sockopt::get_socket_reuseaddr(&s).unwrap()); + assert!(sockopt::get_socket_reuseaddr(&s).unwrap()); #[cfg(not(windows))] { // Set the broadcast flag; - rustix::net::sockopt::set_socket_broadcast(&s, true).unwrap(); + sockopt::set_socket_broadcast(&s, true).unwrap(); // Check that the broadcast flag is set. This has no effect on stream // sockets, and not all platforms even remember the value. #[cfg(not(bsd))] - assert!(rustix::net::sockopt::get_socket_broadcast(&s).unwrap()); + assert!(sockopt::get_socket_broadcast(&s).unwrap()); } // Set the keepalive flag; - rustix::net::sockopt::set_socket_keepalive(&s, true).unwrap(); + sockopt::set_socket_keepalive(&s, true).unwrap(); // Check that the keepalive flag is set. - assert!(rustix::net::sockopt::get_socket_keepalive(&s).unwrap()); + assert!(sockopt::get_socket_keepalive(&s).unwrap()); // Set a linger. - rustix::net::sockopt::set_socket_linger(&s, Some(Duration::new(1, 1))).unwrap(); + sockopt::set_socket_linger(&s, Some(Duration::new(1, 1))).unwrap(); // Check that we have a linger of at least the time we set. - assert!( - dbg!(rustix::net::sockopt::get_socket_linger(&s) - .unwrap() - .unwrap()) - >= Duration::new(1, 1) - ); + assert!(dbg!(sockopt::get_socket_linger(&s).unwrap().unwrap()) >= Duration::new(1, 1)); #[cfg(linux_kernel)] { // Set the passcred flag; - rustix::net::sockopt::set_socket_passcred(&s, true).unwrap(); + sockopt::set_socket_passcred(&s, true).unwrap(); // Check that the passcred flag is set. - assert!(rustix::net::sockopt::get_socket_passcred(&s).unwrap()); + assert!(sockopt::get_socket_passcred(&s).unwrap()); } - // Set the ip ttl. - rustix::net::sockopt::set_ip_ttl(&s, 77).unwrap(); + // Set the receive buffer size. + let size = sockopt::get_socket_recv_buffer_size(&s).unwrap(); + sockopt::set_socket_recv_buffer_size(&s, size * 2).unwrap(); - // Check the ip ttl. - assert_eq!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 77); + // Check that the receive buffer size is set. + assert!(sockopt::get_socket_recv_buffer_size(&s).unwrap() >= size * 2); - #[cfg(not(any(bsd, windows, target_os = "illumos")))] + // Set the send buffer size. + let size = sockopt::get_socket_send_buffer_size(&s).unwrap(); + sockopt::set_socket_send_buffer_size(&s, size * 4).unwrap(); + + // Check that the send buffer size is set. + assert!(sockopt::get_socket_send_buffer_size(&s).unwrap() >= size * 4); + + // Check that the oobinline flag is not initially set. + assert!(!sockopt::get_socket_oobinline(&s).unwrap()); + + // Set the oobinline flag; + sockopt::set_socket_oobinline(&s, true).unwrap(); + + // Check that the oobinline flag is set. + assert!(sockopt::get_socket_oobinline(&s).unwrap()); +} + +// Test `tcp` socket options. +fn test_sockopts_tcp(s: &OwnedFd) { + #[cfg(any(linux_like, taraget_os = "fuchsia"))] { - // Set the multicast loop flag; - rustix::net::sockopt::set_ip_multicast_loop(&s, false).unwrap(); + assert_eq!(sockopt::get_tcp_user_timeout(&s).unwrap(), 0); + sockopt::set_tcp_user_timeout(&s, 7).unwrap(); + assert_eq!(sockopt::get_tcp_user_timeout(&s).unwrap(), 7); + } - // Check that the multicast loop flag is set. - assert!(!rustix::net::sockopt::get_ip_multicast_loop(&s).unwrap()); + assert!(!sockopt::get_tcp_nodelay(&s).unwrap()); + + #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] + { + assert!(sockopt::get_tcp_keepcnt(&s).is_ok()); + assert!(sockopt::get_tcp_keepidle(&s).is_ok()); + assert!(sockopt::get_tcp_keepintvl(&s).is_ok()); } // Set the nodelay flag; - rustix::net::sockopt::set_tcp_nodelay(&s, true).unwrap(); + sockopt::set_tcp_nodelay(&s, true).unwrap(); // Check that the nodelay flag is set. - assert!(rustix::net::sockopt::get_tcp_nodelay(&s).unwrap()); + assert!(sockopt::get_tcp_nodelay(&s).unwrap()); #[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] { // Set keepalive values: - rustix::net::sockopt::set_tcp_keepcnt(&s, 42).unwrap(); - rustix::net::sockopt::set_tcp_keepidle(&s, Duration::from_secs(3601)).unwrap(); - rustix::net::sockopt::set_tcp_keepintvl(&s, Duration::from_secs(61)).unwrap(); + sockopt::set_tcp_keepcnt(&s, 42).unwrap(); + sockopt::set_tcp_keepidle(&s, Duration::from_secs(3601)).unwrap(); + sockopt::set_tcp_keepintvl(&s, Duration::from_secs(61)).unwrap(); // Check keepalive values: - assert_eq!(rustix::net::sockopt::get_tcp_keepcnt(&s).unwrap(), 42); + assert_eq!(sockopt::get_tcp_keepcnt(&s).unwrap(), 42); assert_eq!( - rustix::net::sockopt::get_tcp_keepidle(&s).unwrap(), + sockopt::get_tcp_keepidle(&s).unwrap(), Duration::from_secs(3601) ); assert_eq!( - rustix::net::sockopt::get_tcp_keepintvl(&s).unwrap(), + sockopt::get_tcp_keepintvl(&s).unwrap(), Duration::from_secs(61) ); } +} - // Set the receive buffer size. - let size = rustix::net::sockopt::get_socket_recv_buffer_size(&s).unwrap(); - rustix::net::sockopt::set_socket_recv_buffer_size(&s, size * 2).unwrap(); +#[test] +fn test_sockopts_ipv4() { + let s = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - // Check that the receive buffer size is set. - assert!(rustix::net::sockopt::get_socket_recv_buffer_size(&s).unwrap() >= size * 2); + test_sockopts_socket(&s); - // Set the send buffer size. - let size = rustix::net::sockopt::get_socket_send_buffer_size(&s).unwrap(); - rustix::net::sockopt::set_socket_send_buffer_size(&s, size * 4).unwrap(); + #[cfg(not(any( + apple, + windows, + target_os = "dragonfly", + target_os = "emscripten", + target_os = "espidf", + target_os = "haiku", + target_os = "netbsd", + target_os = "nto", + )))] + assert_eq!(sockopt::get_socket_domain(&s).unwrap(), AddressFamily::INET); + assert_ne!(sockopt::get_ip_ttl(&s).unwrap(), 0); + assert_ne!(sockopt::get_ip_ttl(&s).unwrap(), 77); + #[cfg(not(any(bsd, windows, target_os = "illumos")))] + assert!(sockopt::get_ip_multicast_loop(&s).unwrap()); + #[cfg(not(any(bsd, windows, target_os = "illumos")))] + assert_eq!(sockopt::get_ip_multicast_ttl(&s).unwrap(), 1); - // Check that the send buffer size is set. - assert!(rustix::net::sockopt::get_socket_send_buffer_size(&s).unwrap() >= size * 4); + // Set the ip ttl. + sockopt::set_ip_ttl(&s, 77).unwrap(); + + // Check the ip ttl. + assert_eq!(sockopt::get_ip_ttl(&s).unwrap(), 77); + + #[cfg(not(any(bsd, windows, target_os = "illumos")))] + { + // Set the multicast loop flag; + sockopt::set_ip_multicast_loop(&s, false).unwrap(); + + // Check that the multicast loop flag is set. + assert!(!sockopt::get_ip_multicast_loop(&s).unwrap()); + } + + // Check the initial value of IP TOS, set it, and check it. + #[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "haiku", + target_os = "nto", + target_env = "newlib" + ))] + { + assert_eq!(sockopt::get_ip_tos(&s).unwrap(), 0); + + #[cfg(any(linux_like, target_os = "aix", target_os = "nto"))] + { + sockopt::set_ip_tos(&s, libc::IPTOS_THROUGHPUT).unwrap(); + assert_eq!(sockopt::get_ip_tos(&s).unwrap(), libc::IPTOS_THROUGHPUT); + } + } + + // Check the initial value of IP RECVTOS, set it, and check it. + #[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] + { + assert!(!sockopt::get_ip_recvtos(&s).unwrap()); + sockopt::set_ip_recvtos(&s, true).unwrap(); + assert!(sockopt::get_ip_recvtos(&s).unwrap()); + } + + test_sockopts_tcp(&s); } #[test] fn test_sockopts_ipv6() { - use rustix::net::{AddressFamily, SocketType}; - let s = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - assert_ne!(rustix::net::sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); - match rustix::net::sockopt::get_ipv6_multicast_loop(&s) { + test_sockopts_socket(&s); + + #[cfg(not(any( + apple, + windows, + target_os = "dragonfly", + target_os = "emscripten", + target_os = "espidf", + target_os = "haiku", + target_os = "netbsd", + target_os = "nto", + )))] + assert_eq!( + sockopt::get_socket_domain(&s).unwrap(), + AddressFamily::INET6 + ); + + assert_ne!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); + match sockopt::get_ipv6_multicast_loop(&s) { Ok(multicast_loop) => assert!(multicast_loop), Err(rustix::io::Errno::OPNOTSUPP) => (), Err(rustix::io::Errno::INVAL) => (), Err(rustix::io::Errno::NOPROTOOPT) => (), Err(err) => Err(err).unwrap(), } - assert_ne!(rustix::net::sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); + assert_ne!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); // On NetBSD, `get_ipv6_multicasthops` returns 1 here. It's not evident // why it differs from other OS's. #[cfg(not(target_os = "netbsd"))] - match rustix::net::sockopt::get_ipv6_multicast_hops(&s) { + match sockopt::get_ipv6_multicast_hops(&s) { Ok(hops) => assert_eq!(hops, 0), Err(rustix::io::Errno::NOPROTOOPT) => (), Err(rustix::io::Errno::INVAL) => (), @@ -235,16 +279,16 @@ fn test_sockopts_ipv6() { // Set the IPV4 V6OONLY value. let v6only = rustix::net::sockopt::get_ipv6_v6only(&s).unwrap(); - rustix::net::sockopt::set_ipv6_v6only(&s, !v6only).unwrap(); + sockopt::set_ipv6_v6only(&s, !v6only).unwrap(); // Check that the IPV6 V6ONLY value is set. - assert_eq!(rustix::net::sockopt::get_ipv6_v6only(&s).unwrap(), !v6only); + assert_eq!(sockopt::get_ipv6_v6only(&s).unwrap(), !v6only); // Set the IPV6 multicast loop value. - match rustix::net::sockopt::set_ipv6_multicast_loop(&s, false) { + match sockopt::set_ipv6_multicast_loop(&s, false) { Ok(()) => { // Check that the IPV6 multicast loop value is set. - match rustix::net::sockopt::get_ipv6_multicast_loop(&s) { + match sockopt::get_ipv6_multicast_loop(&s) { Ok(multicast_loop) => assert!(!multicast_loop), Err(err) => Err(err).unwrap(), } @@ -256,14 +300,30 @@ fn test_sockopts_ipv6() { } // Set the IPV6 unicast hops value to the default value. - rustix::net::sockopt::set_ipv6_unicast_hops(&s, None).unwrap(); + sockopt::set_ipv6_unicast_hops(&s, None).unwrap(); // Check that the IPV6 unicast hops value is set. - assert_ne!(rustix::net::sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); + assert_ne!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0); // Set the IPV6 unicast hops value to a specific value. - rustix::net::sockopt::set_ipv6_unicast_hops(&s, Some(8)).unwrap(); + sockopt::set_ipv6_unicast_hops(&s, Some(8)).unwrap(); // Check that the IPV6 unicast hops value is set. - assert_eq!(rustix::net::sockopt::get_ipv6_unicast_hops(&s).unwrap(), 8); + assert_eq!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 8); + + // Check the initial value of IPV6 RECVTCLASS, set it, and check it. + #[cfg(any( + bsd, + linux_like, + target_os = "aix", + target_os = "fuchsia", + target_os = "nto" + ))] + { + assert!(!sockopt::get_ipv6_recvtclass(&s).unwrap()); + sockopt::set_ipv6_recvtclass(&s, true).unwrap(); + assert!(sockopt::get_ipv6_recvtclass(&s).unwrap()); + } + + test_sockopts_tcp(&s); }