summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/linux_raw/net
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/net')
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/addr.rs172
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/mod.rs6
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs175
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/send_recv.rs42
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/syscalls.rs1248
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/types.rs282
-rw-r--r--vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs60
7 files changed, 1985 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/linux_raw/net/addr.rs b/vendor/rustix/src/backend/linux_raw/net/addr.rs
new file mode 100644
index 000000000..d5683f34e
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/addr.rs
@@ -0,0 +1,172 @@
+//! IPv4, IPv6, and Socket addresses.
+//!
+//! # Safety
+//!
+//! Linux's IPv6 type contains a union.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::ffi::CStr;
+use crate::{io, path};
+use core::convert::TryInto;
+use core::{fmt, slice};
+
+/// `struct sockaddr_un`
+#[derive(Clone)]
+#[doc(alias = "sockaddr_un")]
+pub struct SocketAddrUnix {
+ pub(crate) unix: c::sockaddr_un,
+ len: c::socklen_t,
+}
+
+impl SocketAddrUnix {
+ /// Construct a new Unix-domain address from a filesystem path.
+ #[inline]
+ pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
+ path.into_with_c_str(Self::_new)
+ }
+
+ #[inline]
+ fn _new(path: &CStr) -> io::Result<Self> {
+ let mut unix = Self::init();
+ let bytes = path.to_bytes_with_nul();
+ if bytes.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ for (i, b) in bytes.iter().enumerate() {
+ unix.sun_path[i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + bytes.len();
+ let len = len.try_into().unwrap();
+ Ok(Self { unix, len })
+ }
+
+ /// Construct a new abstract Unix-domain address from a byte slice.
+ #[inline]
+ pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
+ let mut unix = Self::init();
+ if 1 + name.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ unix.sun_path[0] = b'\0' as c::c_char;
+ for (i, b) in name.iter().enumerate() {
+ unix.sun_path[1 + i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + 1 + name.len();
+ let len = len.try_into().unwrap();
+ Ok(Self { unix, len })
+ }
+
+ fn init() -> c::sockaddr_un {
+ c::sockaddr_un {
+ sun_family: c::AF_UNIX as _,
+ sun_path: [0; 108],
+ }
+ }
+
+ /// For a filesystem path address, return the path.
+ #[inline]
+ pub fn path(&self) -> Option<&CStr> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
+ // `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
+ unsafe {
+ Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ )))
+ }
+ } else {
+ None
+ }
+ }
+
+ /// For an abstract address, return the identifier.
+ #[inline]
+ pub fn abstract_name(&self) -> Option<&[u8]> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[1..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
+ unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub(crate) fn addr_len(&self) -> c::socklen_t {
+ self.len
+ }
+
+ #[inline]
+ pub(crate) fn len(&self) -> usize {
+ self.addr_len() as usize
+ }
+}
+
+impl PartialEq for SocketAddrUnix {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl Eq for SocketAddrUnix {}
+
+impl PartialOrd for SocketAddrUnix {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl Ord for SocketAddrUnix {
+ #[inline]
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+impl core::hash::Hash for SocketAddrUnix {
+ #[inline]
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ let self_len = self.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].hash(state)
+ }
+}
+
+impl fmt::Debug for SocketAddrUnix {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.path() {
+ path.fmt(fmt)
+ } else if let Some(name) = self.abstract_name() {
+ name.fmt(fmt)
+ } else {
+ "(unnamed)".fmt(fmt)
+ }
+ }
+}
+
+/// `struct sockaddr_storage` as a raw struct.
+pub type SocketAddrStorage = c::sockaddr;
+
+/// Return the offset of the `sun_path` field of `sockaddr_un`.
+#[inline]
+pub(crate) fn offsetof_sun_path() -> usize {
+ let z = c::sockaddr_un {
+ sun_family: 0_u16,
+ sun_path: [0; 108],
+ };
+ (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
+}
diff --git a/vendor/rustix/src/backend/linux_raw/net/mod.rs b/vendor/rustix/src/backend/linux_raw/net/mod.rs
new file mode 100644
index 000000000..f2273db1b
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/mod.rs
@@ -0,0 +1,6 @@
+pub(crate) mod addr;
+pub(crate) mod read_sockaddr;
+pub(crate) mod send_recv;
+pub(crate) mod syscalls;
+pub(crate) mod types;
+pub(crate) mod write_sockaddr;
diff --git a/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs b/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs
new file mode 100644
index 000000000..b9bc09b96
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs
@@ -0,0 +1,175 @@
+//! The BSD sockets API requires us to read the `ss_family` field before
+//! we can interpret the rest of a `sockaddr` produced by the kernel.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::io;
+use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use alloc::vec::Vec;
+use core::mem::size_of;
+
+// This must match the header of `sockaddr`.
+#[repr(C)]
+struct sockaddr_header {
+ ss_family: u16,
+}
+
+/// Read the `ss_family` field from a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+#[inline]
+unsafe fn read_ss_family(storage: *const c::sockaddr) -> u16 {
+ // Assert that we know the layout of `sockaddr`.
+ let _ = c::sockaddr {
+ __storage: c::sockaddr_storage {
+ __bindgen_anon_1: linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1 {
+ __bindgen_anon_1:
+ linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
+ ss_family: 0_u16,
+ __data: [0; 126_usize],
+ },
+ },
+ },
+ };
+
+ (*storage.cast::<sockaddr_header>()).ss_family
+}
+
+/// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we
+/// can test for `AF_UNSPEC` to test whether it was stored to.
+#[inline]
+pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) {
+ (*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _;
+}
+
+/// Read a socket address encoded in a platform-specific format.
+///
+/// # Safety
+///
+/// `storage` must point to valid socket address storage.
+pub(crate) unsafe fn read_sockaddr(
+ storage: *const c::sockaddr,
+ len: usize,
+) -> io::Result<SocketAddrAny> {
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ if len < size_of::<c::sa_family_t>() {
+ return Err(io::Errno::INVAL);
+ }
+ match read_ss_family(storage).into() {
+ c::AF_INET => {
+ if len < size_of::<c::sockaddr_in>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in>();
+ Ok(SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
+ u16::from_be(decode.sin_port),
+ )))
+ }
+ c::AF_INET6 => {
+ if len < size_of::<c::sockaddr_in6>() {
+ return Err(io::Errno::INVAL);
+ }
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ Ok(SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ decode.sin6_scope_id,
+ )))
+ }
+ c::AF_UNIX => {
+ if len < offsetof_sun_path {
+ return Err(io::Errno::INVAL);
+ }
+ if len == offsetof_sun_path {
+ Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..])?))
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+ assert_eq!(
+ decode.sun_path[len - 1 - offsetof_sun_path],
+ b'\0' as c::c_char
+ );
+ Ok(SocketAddrAny::Unix(SocketAddrUnix::new(
+ decode.sun_path[..len - 1 - offsetof_sun_path]
+ .iter()
+ .map(|c| *c as u8)
+ .collect::<Vec<u8>>(),
+ )?))
+ }
+ }
+ _ => Err(io::Errno::NOTSUP),
+ }
+}
+
+/// Read a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+pub(crate) unsafe fn maybe_read_sockaddr_os(
+ storage: *const c::sockaddr,
+ len: usize,
+) -> Option<SocketAddrAny> {
+ if len == 0 {
+ None
+ } else {
+ Some(read_sockaddr_os(storage, len))
+ }
+}
+
+/// Read a socket address returned from the OS.
+///
+/// # Safety
+///
+/// `storage` must point to a valid socket address returned from the OS.
+pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) -> SocketAddrAny {
+ let offsetof_sun_path = super::addr::offsetof_sun_path();
+
+ assert!(len >= size_of::<c::sa_family_t>());
+ match read_ss_family(storage).into() {
+ c::AF_INET => {
+ assert!(len >= size_of::<c::sockaddr_in>());
+ let decode = *storage.cast::<c::sockaddr_in>();
+ SocketAddrAny::V4(SocketAddrV4::new(
+ Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
+ u16::from_be(decode.sin_port),
+ ))
+ }
+ c::AF_INET6 => {
+ assert!(len >= size_of::<c::sockaddr_in6>());
+ let decode = *storage.cast::<c::sockaddr_in6>();
+ SocketAddrAny::V6(SocketAddrV6::new(
+ Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8),
+ u16::from_be(decode.sin6_port),
+ u32::from_be(decode.sin6_flowinfo),
+ decode.sin6_scope_id,
+ ))
+ }
+ c::AF_UNIX => {
+ assert!(len >= offsetof_sun_path);
+ if len == offsetof_sun_path {
+ SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())
+ } else {
+ let decode = *storage.cast::<c::sockaddr_un>();
+ assert_eq!(
+ decode.sun_path[len - 1 - offsetof_sun_path],
+ b'\0' as c::c_char
+ );
+ SocketAddrAny::Unix(
+ SocketAddrUnix::new(
+ decode.sun_path[..len - 1 - offsetof_sun_path]
+ .iter()
+ .map(|c| *c as u8)
+ .collect::<Vec<u8>>(),
+ )
+ .unwrap(),
+ )
+ }
+ }
+ other => unimplemented!("{:?}", other),
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/net/send_recv.rs b/vendor/rustix/src/backend/linux_raw/net/send_recv.rs
new file mode 100644
index 000000000..888e81e2b
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/send_recv.rs
@@ -0,0 +1,42 @@
+use super::super::c;
+use bitflags::bitflags;
+
+bitflags! {
+ /// `MSG_*`
+ pub struct SendFlags: u32 {
+ /// `MSG_CONFIRM`
+ const CONFIRM = c::MSG_CONFIRM;
+ /// `MSG_DONTROUTE`
+ const DONTROUTE = c::MSG_DONTROUTE;
+ /// `MSG_DONTWAIT`
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_EOT`
+ const EOT = c::MSG_EOR;
+ /// `MSG_MORE`
+ const MORE = c::MSG_MORE;
+ /// `MSG_NOSIGNAL`
+ const NOSIGNAL = c::MSG_NOSIGNAL;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ }
+}
+
+bitflags! {
+ /// `MSG_*`
+ pub struct RecvFlags: u32 {
+ /// `MSG_CMSG_CLOEXEC`
+ const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC;
+ /// `MSG_DONTWAIT`
+ const DONTWAIT = c::MSG_DONTWAIT;
+ /// `MSG_ERRQUEUE`
+ const ERRQUEUE = c::MSG_ERRQUEUE;
+ /// `MSG_OOB`
+ const OOB = c::MSG_OOB;
+ /// `MSG_PEEK`
+ const PEEK = c::MSG_PEEK;
+ /// `MSG_TRUNC`
+ const TRUNC = c::MSG_TRUNC;
+ /// `MSG_WAITALL`
+ const WAITALL = c::MSG_WAITALL;
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/net/syscalls.rs b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs
new file mode 100644
index 000000000..7b9947a03
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs
@@ -0,0 +1,1248 @@
+//! linux_raw syscalls supporting `rustix::net`.
+//!
+//! # Safety
+//!
+//! See the `rustix::backend` module documentation for details.
+#![allow(unsafe_code)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use super::super::c;
+use super::super::conv::{
+ by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, slice_mut,
+ socklen_t, zero,
+};
+use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os};
+use super::send_recv::{RecvFlags, SendFlags};
+use super::types::{AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType};
+use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
+use crate::fd::{BorrowedFd, OwnedFd};
+use crate::io;
+use crate::net::{SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t};
+use core::convert::TryInto;
+use core::mem::MaybeUninit;
+#[cfg(target_arch = "x86")]
+use {
+ super::super::conv::{slice_just_addr, x86_sys},
+ super::super::reg::{ArgReg, SocketArg},
+ linux_raw_sys::general::{
+ SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME,
+ SYS_GETSOCKOPT, SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_SEND, SYS_SENDTO, SYS_SETSOCKOPT,
+ SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR,
+ },
+};
+
+#[inline]
+pub(crate) fn socket(
+ family: AddressFamily,
+ type_: SocketType,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(__NR_socket, family, type_, protocol))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKET),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ type_.into(),
+ protocol.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn socket_with(
+ family: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socket,
+ family,
+ (type_, flags),
+ protocol
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKET),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ (type_, flags).into(),
+ protocol.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn socketpair(
+ family: AddressFamily,
+ type_: SocketType,
+ flags: SocketFlags,
+ protocol: Protocol,
+) -> io::Result<(OwnedFd, OwnedFd)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(
+ __NR_socketpair,
+ family,
+ (type_, flags),
+ protocol,
+ &mut result
+ ))?;
+ let [fd0, fd1] = result.assume_init();
+ Ok((fd0, fd1))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_SOCKETPAIR),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ family.into(),
+ (type_, flags).into(),
+ protocol.into(),
+ (&mut result).into(),
+ ])
+ ))?;
+ let [fd0, fd1] = result.assume_init();
+ Ok((fd0, fd1))
+ }
+}
+
+#[inline]
+pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(__NR_accept, fd, zero(), zero()))?;
+ Ok(fd)
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), zero(), zero()])
+ ))?;
+ Ok(fd)
+ }
+}
+
+#[inline]
+pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: AcceptFlags) -> io::Result<OwnedFd> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?;
+ Ok(fd)
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let fd = ret_owned_fd(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT4),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()])
+ ))?;
+ Ok(fd)
+ }
+}
+
+#[inline]
+pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_accept,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn acceptfrom_with(
+ fd: BorrowedFd<'_>,
+ flags: AcceptFlags,
+) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_accept4,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen),
+ flags
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ let fd = ret_owned_fd(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_ACCEPT4),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ flags.into(),
+ ])
+ ))?;
+ Ok((
+ fd,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_shutdown,
+ fd,
+ c_uint(how as c::c_uint)
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SHUTDOWN),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ )))]
+ unsafe {
+ ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags))
+ }
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+ ))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ zero(),
+ zero()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SEND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), buf_addr, buf_len, flags.into()])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_v4(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV4,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_v6(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrV6,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn sendto_unix(
+ fd: BorrowedFd<'_>,
+ buf: &[u8],
+ flags: SendFlags,
+ addr: &SocketAddrUnix,
+) -> io::Result<usize> {
+ let (buf_addr, buf_len) = slice(buf);
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_sendto,
+ fd,
+ buf_addr,
+ buf_len,
+ flags,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_SENDTO),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr,
+ buf_len,
+ flags.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ #[cfg(not(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86",
+ target_arch = "x86_64",
+ )))]
+ unsafe {
+ ret_usize(syscall!(__NR_recv, fd, buf_addr_mut, buf_len, flags))
+ }
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "riscv64",
+ target_arch = "x86_64",
+ ))]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_recvfrom,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ flags,
+ zero(),
+ zero()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret_usize(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_RECV),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr_mut,
+ buf_len,
+ flags.into(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn recvfrom(
+ fd: BorrowedFd<'_>,
+ buf: &mut [u8],
+ flags: RecvFlags,
+) -> io::Result<(usize, Option<SocketAddrAny>)> {
+ let (buf_addr_mut, buf_len) = slice_mut(buf);
+
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+
+ unsafe {
+ // `recvfrom` does not write to the storage if the socket is
+ // connection-oriented sockets, so we initialize the family field to
+ // `AF_UNSPEC` so that we can detect this case.
+ initialize_family_to_unspec(storage.as_mut_ptr());
+
+ #[cfg(not(target_arch = "x86"))]
+ let nread = ret_usize(syscall!(
+ __NR_recvfrom,
+ fd,
+ buf_addr_mut,
+ buf_len,
+ flags,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ #[cfg(target_arch = "x86")]
+ let nread = ret_usize(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_RECVFROM),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ buf_addr_mut,
+ buf_len,
+ flags.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+
+ Ok((
+ nread,
+ maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_getpeername,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok(maybe_read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETPEERNAME),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok(maybe_read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_getsockname,
+ fd,
+ &mut storage,
+ by_mut(&mut addrlen)
+ ))?;
+ Ok(read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t;
+ let mut storage = MaybeUninit::<sockaddr>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETSOCKNAME),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ (&mut storage).into(),
+ by_mut(&mut addrlen),
+ ])
+ ))?;
+ Ok(read_sockaddr_os(
+ &storage.assume_init(),
+ addrlen.try_into().unwrap(),
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_bind,
+ fd,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_BIND),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v4(addr)),
+ size_of::<sockaddr_in, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>()
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&encode_sockaddr_v6(addr)),
+ size_of::<sockaddr_in6, _>(),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_connect,
+ fd,
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len())
+ ))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_CONNECT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ by_ref(&addr.unix),
+ socklen_t(addr.addr_len()),
+ ])
+ ))
+ }
+}
+
+#[inline]
+pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ ret(syscall_readonly!(__NR_listen, fd, c_int(backlog)))
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ ret(syscall_readonly!(
+ __NR_socketcall,
+ x86_sys(SYS_LISTEN),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[fd.into(), c_int(backlog)])
+ ))
+ }
+}
+
+pub(crate) mod sockopt {
+ use super::{c, BorrowedFd};
+ use crate::io;
+ use crate::net::sockopt::Timeout;
+ use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
+ use c::{SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD};
+ use core::convert::TryInto;
+ use core::time::Duration;
+ use linux_raw_sys::general::{__kernel_timespec, timeval};
+
+ // TODO: With Rust 1.53 we can use `Duration::ZERO` instead.
+ const DURATION_ZERO: Duration = Duration::from_secs(0);
+
+ #[inline]
+ fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: u32, optname: u32) -> io::Result<T> {
+ use super::*;
+
+ let mut optlen = core::mem::size_of::<T>();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ #[cfg(not(target_arch = "x86"))]
+ unsafe {
+ let mut value = MaybeUninit::<T>::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::<T>(),
+ "unexpected getsockopt size"
+ );
+ Ok(value.assume_init())
+ }
+ #[cfg(target_arch = "x86")]
+ unsafe {
+ let mut value = MaybeUninit::<T>::uninit();
+ ret(syscall!(
+ __NR_socketcall,
+ x86_sys(SYS_GETSOCKOPT),
+ slice_just_addr::<ArgReg<SocketArg>, _>(&[
+ fd.into(),
+ c_uint(level),
+ c_uint(optname),
+ (&mut value).into(),
+ by_mut(&mut optlen),
+ ])
+ ))?;
+ assert_eq!(
+ optlen as usize,
+ core::mem::size_of::<T>(),
+ "unexpected getsockopt size"
+ );
+ Ok(value.assume_init())
+ }
+ }
+
+ #[inline]
+ fn setsockopt<T: Copy>(
+ fd: BorrowedFd<'_>,
+ level: u32,
+ optname: u32,
+ value: T,
+ ) -> io::Result<()> {
+ use super::*;
+
+ let optlen = core::mem::size_of::<T>().try_into().unwrap();
+ debug_assert!(
+ optlen as usize >= core::mem::size_of::<c::c_int>(),
+ "Socket APIs don't ever use `bool` directly"
+ );
+
+ #[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::<ArgReg<SocketArg>, _>(&[
+ 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<SocketType> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_TYPE)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_REUSEADDR,
+ from_bool(reuseaddr),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::SOL_SOCKET as _,
+ c::SO_BROADCAST,
+ from_bool(broadcast),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_linger(
+ fd: BorrowedFd<'_>,
+ linger: Option<Duration>,
+ ) -> io::Result<()> {
+ // Convert `linger` to seconds, rounding up.
+ let l_linger = if let Some(linger) = linger {
+ let mut l_linger = linger.as_secs();
+ if linger.subsec_nanos() != 0 {
+ l_linger = l_linger.checked_add(1).ok_or(io::Errno::INVAL)?;
+ }
+ l_linger.try_into().map_err(|_e| io::Errno::INVAL)?
+ } 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<Option<Duration>> {
+ let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?;
+ // TODO: With Rust 1.50, this could use `.then`.
+ Ok(if linger.l_onoff != 0 {
+ Some(Duration::from_secs(linger.l_linger as u64))
+ } else {
+ None
+ })
+ }
+
+ #[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<bool> {
+ getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_socket_timeout(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+ ) -> io::Result<()> {
+ let time = duration_to_linux(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 `timeval` instead of
+ /// `__kernel_timespec` and `_OLD` constants instead of `_NEW`.
+ fn set_socket_timeout_old(
+ fd: BorrowedFd<'_>,
+ id: Timeout,
+ timeout: Option<Duration>,
+ ) -> io::Result<()> {
+ let time = duration_to_linux_old(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<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_NEW,
+ Timeout::Send => SO_SNDTIMEO_NEW,
+ };
+ let time: __kernel_timespec = 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(time))
+ }
+
+ /// Same as `get_socket_timeout` but uses `timeval` instead of
+ /// `__kernel_timespec` and `_OLD` constants instead of `_NEW`.
+ fn get_socket_timeout_old(fd: BorrowedFd<'_>, id: Timeout) -> io::Result<Option<Duration>> {
+ let optname = match id {
+ Timeout::Recv => SO_RCVTIMEO_OLD,
+ Timeout::Send => SO_SNDTIMEO_OLD,
+ };
+ let time: timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
+ Ok(duration_from_linux_old(time))
+ }
+
+ /// Convert a C `timespec` to a Rust `Option<Duration>`.
+ #[inline]
+ fn duration_from_linux(time: __kernel_timespec) -> Option<Duration> {
+ if time.tv_sec == 0 && time.tv_nsec == 0 {
+ None
+ } else {
+ Some(
+ Duration::from_secs(time.tv_sec as u64) + Duration::from_nanos(time.tv_nsec as u64),
+ )
+ }
+ }
+
+ /// Like `duration_from_linux` but uses Linux's old 32-bit `timeval`.
+ fn duration_from_linux_old(time: timeval) -> Option<Duration> {
+ 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<Duration>` to a C `timespec`.
+ #[inline]
+ fn duration_to_linux(timeout: Option<Duration>) -> io::Result<__kernel_timespec> {
+ Ok(match timeout {
+ Some(timeout) => {
+ if timeout == DURATION_ZERO {
+ return Err(io::Errno::INVAL);
+ }
+ let mut timeout = __kernel_timespec {
+ tv_sec: timeout.as_secs().try_into().unwrap_or(i64::MAX),
+ tv_nsec: timeout.subsec_nanos().into(),
+ };
+ if timeout.tv_sec == 0 && timeout.tv_nsec == 0 {
+ timeout.tv_nsec = 1;
+ }
+ timeout
+ }
+ None => __kernel_timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ },
+ })
+ }
+
+ /// Like `duration_to_linux` but uses Linux's old 32-bit `timeval`.
+ fn duration_to_linux_old(timeout: Option<Duration>) -> io::Result<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 = 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 => timeval {
+ tv_sec: 0,
+ tv_usec: 0,
+ },
+ })
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY, from_bool(only_v6))
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IP as _,
+ c::IP_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL, multicast_ttl)
+ }
+
+ #[inline]
+ pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_multicast_loop(
+ fd: BorrowedFd<'_>,
+ multicast_loop: bool,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IPV6 as _,
+ c::IPV6_MULTICAST_LOOP,
+ from_bool(multicast_loop),
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_MULTICAST_LOOP).map(to_bool)
+ }
+
+ #[inline]
+ pub(crate) fn set_ipv6_multicast_hops(
+ fd: BorrowedFd<'_>,
+ multicast_hops: u32,
+ ) -> io::Result<()> {
+ setsockopt(
+ fd,
+ c::IPPROTO_IP as _,
+ c::IPV6_MULTICAST_LOOP,
+ multicast_hops,
+ )
+ }
+
+ #[inline]
+ pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result<u32> {
+ getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_LOOP)
+ }
+
+ #[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 set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
+ setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY, from_bool(nodelay))
+ }
+
+ #[inline]
+ pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
+ getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool)
+ }
+
+ #[inline]
+ 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::general::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
+ }
+}
diff --git a/vendor/rustix/src/backend/linux_raw/net/types.rs b/vendor/rustix/src/backend/linux_raw/net/types.rs
new file mode 100644
index 000000000..b8f786b3f
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/types.rs
@@ -0,0 +1,282 @@
+use super::super::c;
+use bitflags::bitflags;
+
+/// A type for holding raw integer socket types.
+#[doc(hidden)]
+pub type RawSocketType = u32;
+
+/// `SOCK_*` constants for use with [`socket`].
+///
+/// [`socket`]: crate::net::socket
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct SocketType(pub(crate) RawSocketType);
+
+#[rustfmt::skip]
+impl SocketType {
+ /// `SOCK_STREAM`
+ pub const STREAM: Self = Self(c::SOCK_STREAM);
+
+ /// `SOCK_DGRAM`
+ pub const DGRAM: Self = Self(c::SOCK_DGRAM);
+
+ /// `SOCK_SEQPACKET`
+ pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET);
+
+ /// `SOCK_RAW`
+ pub const RAW: Self = Self(c::SOCK_RAW);
+
+ /// `SOCK_RDM`
+ pub const RDM: Self = Self(c::SOCK_RDM);
+
+ /// Constructs a `SocketType` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawSocketType) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `SocketType`.
+ #[inline]
+ pub const fn as_raw(self) -> RawSocketType {
+ self.0
+ }
+}
+
+/// A type for holding raw integer address families.
+#[doc(hidden)]
+pub type RawAddressFamily = c::sa_family_t;
+
+/// `AF_*` constants.
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct AddressFamily(pub(crate) RawAddressFamily);
+
+#[rustfmt::skip]
+impl AddressFamily {
+ /// `AF_UNSPEC`
+ pub const UNSPEC: Self = Self(c::AF_UNSPEC as _);
+ /// `AF_INET`
+ pub const INET: Self = Self(c::AF_INET as _);
+ /// `AF_INET6`
+ pub const INET6: Self = Self(c::AF_INET6 as _);
+ /// `AF_NETLINK`
+ pub const NETLINK: Self = Self(c::AF_NETLINK as _);
+ /// `AF_UNIX`, aka `AF_LOCAL`
+ #[doc(alias = "LOCAL")]
+ pub const UNIX: Self = Self(c::AF_UNIX as _);
+ /// `AF_AX25`
+ pub const AX25: Self = Self(c::AF_AX25 as _);
+ /// `AF_IPX`
+ pub const IPX: Self = Self(c::AF_IPX as _);
+ /// `AF_APPLETALK`
+ pub const APPLETALK: Self = Self(c::AF_APPLETALK as _);
+ /// `AF_NETROM`
+ pub const NETROM: Self = Self(c::AF_NETROM as _);
+ /// `AF_BRIDGE`
+ pub const BRIDGE: Self = Self(c::AF_BRIDGE as _);
+ /// `AF_ATMPVC`
+ pub const ATMPVC: Self = Self(c::AF_ATMPVC as _);
+ /// `AF_X25`
+ pub const X25: Self = Self(c::AF_X25 as _);
+ /// `AF_ROSE`
+ pub const ROSE: Self = Self(c::AF_ROSE as _);
+ /// `AF_DECnet`
+ #[allow(non_upper_case_globals)]
+ pub const DECnet: Self = Self(c::AF_DECnet as _);
+ /// `AF_NETBEUI`
+ pub const NETBEUI: Self = Self(c::AF_NETBEUI as _);
+ /// `AF_SECURITY`
+ pub const SECURITY: Self = Self(c::AF_SECURITY as _);
+ /// `AF_KEY`
+ pub const KEY: Self = Self(c::AF_KEY as _);
+ /// `AF_PACKET`
+ pub const PACKET: Self = Self(c::AF_PACKET as _);
+ /// `AF_ASH`
+ pub const ASH: Self = Self(c::AF_ASH as _);
+ /// `AF_ECONET`
+ pub const ECONET: Self = Self(c::AF_ECONET as _);
+ /// `AF_ATMSVC`
+ pub const ATMSVC: Self = Self(c::AF_ATMSVC as _);
+ /// `AF_RDS`
+ pub const RDS: Self = Self(c::AF_RDS as _);
+ /// `AF_SNA`
+ pub const SNA: Self = Self(c::AF_SNA as _);
+ /// `AF_IRDA`
+ pub const IRDA: Self = Self(c::AF_IRDA as _);
+ /// `AF_PPPOX`
+ pub const PPPOX: Self = Self(c::AF_PPPOX as _);
+ /// `AF_WANPIPE`
+ pub const WANPIPE: Self = Self(c::AF_WANPIPE as _);
+ /// `AF_LLC`
+ pub const LLC: Self = Self(c::AF_LLC as _);
+ /// `AF_CAN`
+ pub const CAN: Self = Self(c::AF_CAN as _);
+ /// `AF_TIPC`
+ pub const TIPC: Self = Self(c::AF_TIPC as _);
+ /// `AF_BLUETOOTH`
+ pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _);
+ /// `AF_IUCV`
+ pub const IUCV: Self = Self(c::AF_IUCV as _);
+ /// `AF_RXRPC`
+ pub const RXRPC: Self = Self(c::AF_RXRPC as _);
+ /// `AF_ISDN`
+ pub const ISDN: Self = Self(c::AF_ISDN as _);
+ /// `AF_PHONET`
+ pub const PHONET: Self = Self(c::AF_PHONET as _);
+ /// `AF_IEEE802154`
+ pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _);
+
+ /// Constructs a `AddressFamily` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawAddressFamily) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `AddressFamily`.
+ #[inline]
+ pub const fn as_raw(self) -> RawAddressFamily {
+ self.0
+ }
+}
+
+/// A type for holding raw integer protocols.
+#[doc(hidden)]
+pub type RawProtocol = u32;
+
+/// `IPPROTO_*`
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+pub struct Protocol(pub(crate) RawProtocol);
+
+#[rustfmt::skip]
+impl Protocol {
+ /// `IPPROTO_IP`
+ pub const IP: Self = Self(c::IPPROTO_IP as _);
+ /// `IPPROTO_ICMP`
+ pub const ICMP: Self = Self(c::IPPROTO_ICMP as _);
+ /// `IPPROTO_IGMP`
+ pub const IGMP: Self = Self(c::IPPROTO_IGMP as _);
+ /// `IPPROTO_IPIP`
+ pub const IPIP: Self = Self(c::IPPROTO_IPIP as _);
+ /// `IPPROTO_TCP`
+ pub const TCP: Self = Self(c::IPPROTO_TCP as _);
+ /// `IPPROTO_EGP`
+ pub const EGP: Self = Self(c::IPPROTO_EGP as _);
+ /// `IPPROTO_PUP`
+ pub const PUP: Self = Self(c::IPPROTO_PUP as _);
+ /// `IPPROTO_UDP`
+ pub const UDP: Self = Self(c::IPPROTO_UDP as _);
+ /// `IPPROTO_IDP`
+ pub const IDP: Self = Self(c::IPPROTO_IDP as _);
+ /// `IPPROTO_TP`
+ pub const TP: Self = Self(c::IPPROTO_TP as _);
+ /// `IPPROTO_DCCP`
+ pub const DCCP: Self = Self(c::IPPROTO_DCCP as _);
+ /// `IPPROTO_IPV6`
+ pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _);
+ /// `IPPROTO_RSVP`
+ pub const RSVP: Self = Self(c::IPPROTO_RSVP as _);
+ /// `IPPROTO_GRE`
+ pub const GRE: Self = Self(c::IPPROTO_GRE as _);
+ /// `IPPROTO_ESP`
+ pub const ESP: Self = Self(c::IPPROTO_ESP as _);
+ /// `IPPROTO_AH`
+ pub const AH: Self = Self(c::IPPROTO_AH as _);
+ /// `IPPROTO_MTP`
+ pub const MTP: Self = Self(c::IPPROTO_MTP as _);
+ /// `IPPROTO_BEETPH`
+ pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _);
+ /// `IPPROTO_ENCAP`
+ pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _);
+ /// `IPPROTO_PIM`
+ pub const PIM: Self = Self(c::IPPROTO_PIM as _);
+ /// `IPPROTO_COMP`
+ pub const COMP: Self = Self(c::IPPROTO_COMP as _);
+ /// `IPPROTO_SCTP`
+ pub const SCTP: Self = Self(c::IPPROTO_SCTP as _);
+ /// `IPPROTO_UDPLITE`
+ pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _);
+ /// `IPPROTO_MPLS`
+ pub const MPLS: Self = Self(c::IPPROTO_MPLS as _);
+ /// `IPPROTO_ETHERNET`
+ pub const ETHERNET: Self = Self(c::IPPROTO_ETHERNET as _);
+ /// `IPPROTO_RAW`
+ pub const RAW: Self = Self(c::IPPROTO_RAW as _);
+ /// `IPPROTO_MPTCP`
+ pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _);
+ /// `IPPROTO_FRAGMENT`
+ pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _);
+ /// `IPPROTO_ICMPV6`
+ pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _);
+ /// `IPPROTO_MH`
+ pub const MH: Self = Self(c::IPPROTO_MH as _);
+ /// `IPPROTO_ROUTING`
+ pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _);
+
+ /// Constructs a `Protocol` from a raw integer.
+ #[inline]
+ pub const fn from_raw(raw: RawProtocol) -> Self {
+ Self(raw)
+ }
+
+ /// Returns the raw integer for this `Protocol`.
+ #[inline]
+ pub const fn as_raw(self) -> RawProtocol {
+ self.0
+ }
+}
+
+/// `SHUT_*` constants for use with [`shutdown`].
+///
+/// [`shutdown`]: crate::net::shutdown
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+#[repr(u32)]
+pub enum Shutdown {
+ /// `SHUT_WR`—Disable further read operations.
+ Read = c::SHUT_RD,
+ /// `SHUT_WR`—Disable further write operations.
+ Write = c::SHUT_WR,
+ /// `SHUT_RDWR`—Disable further read and write operations.
+ ReadWrite = c::SHUT_RDWR,
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`accept_with`] and [`acceptfrom_with`].
+ ///
+ /// [`accept_with`]: crate::net::accept_with
+ /// [`acceptfrom_with`]: crate::net::acceptfrom_with
+ pub struct AcceptFlags: c::c_uint {
+ /// `SOCK_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+ /// `SOCK_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ }
+}
+
+bitflags! {
+ /// `SOCK_*` constants for use with [`socket`].
+ ///
+ /// [`socket`]: crate::net::socket
+ pub struct SocketFlags: c::c_uint {
+ /// `SOCK_NONBLOCK`
+ const NONBLOCK = c::O_NONBLOCK;
+
+ /// `SOCK_CLOEXEC`
+ const CLOEXEC = c::O_CLOEXEC;
+ }
+}
+
+/// 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 {
+ /// `SO_RCVTIMEO`—Timeout for receiving.
+ Recv = c::SO_RCVTIMEO_NEW,
+
+ /// `SO_SNDTIMEO`—Timeout for sending.
+ Send = c::SO_SNDTIMEO_NEW,
+}
diff --git a/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs b/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs
new file mode 100644
index 000000000..17abd96a0
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs
@@ -0,0 +1,60 @@
+//! The BSD sockets API requires us to read the `ss_family` field before
+//! we can interpret the rest of a `sockaddr` produced by the kernel.
+#![allow(unsafe_code)]
+
+use super::super::c;
+use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrUnix, SocketAddrV4, SocketAddrV6};
+use core::mem::size_of;
+
+pub(crate) unsafe fn write_sockaddr(
+ addr: &SocketAddrAny,
+ storage: *mut SocketAddrStorage,
+) -> usize {
+ match addr {
+ SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage),
+ SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage),
+ SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage),
+ }
+}
+
+pub(crate) unsafe fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
+ c::sockaddr_in {
+ sin_family: c::AF_INET as _,
+ sin_port: u16::to_be(v4.port()),
+ sin_addr: c::in_addr {
+ s_addr: u32::from_ne_bytes(v4.ip().octets()),
+ },
+ __pad: [0_u8; 8],
+ }
+}
+
+unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v4(v4);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in>()
+}
+
+pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
+ c::sockaddr_in6 {
+ sin6_family: c::AF_INET6 as _,
+ sin6_port: u16::to_be(v6.port()),
+ sin6_flowinfo: u32::to_be(v6.flowinfo()),
+ sin6_addr: c::in6_addr {
+ in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 {
+ u6_addr8: v6.ip().octets(),
+ },
+ },
+ sin6_scope_id: v6.scope_id(),
+ }
+}
+
+unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize {
+ let encoded = encode_sockaddr_v6(v6);
+ core::ptr::write(storage.cast(), encoded);
+ size_of::<c::sockaddr_in6>()
+}
+
+unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize {
+ core::ptr::write(storage.cast(), unix.unix);
+ unix.len()
+}