diff options
| author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 | 
| commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
| tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rustix/src/net | |
| parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
| download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip  | |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rustix/src/net')
| -rw-r--r-- | vendor/rustix/src/net/mod.rs | 31 | ||||
| -rw-r--r-- | vendor/rustix/src/net/send_recv/mod.rs | 380 | ||||
| -rw-r--r-- | vendor/rustix/src/net/send_recv/msg.rs | 966 | ||||
| -rw-r--r-- | vendor/rustix/src/net/socket.rs | 750 | ||||
| -rw-r--r-- | vendor/rustix/src/net/socket_addr_any.rs | 113 | ||||
| -rw-r--r-- | vendor/rustix/src/net/socketpair.rs | 36 | ||||
| -rw-r--r-- | vendor/rustix/src/net/sockopt.rs | 1382 | ||||
| -rw-r--r-- | vendor/rustix/src/net/types.rs | 1495 | ||||
| -rw-r--r-- | vendor/rustix/src/net/wsa.rs | 49 | 
9 files changed, 5202 insertions, 0 deletions
diff --git a/vendor/rustix/src/net/mod.rs b/vendor/rustix/src/net/mod.rs new file mode 100644 index 0000000..73ae2f0 --- /dev/null +++ b/vendor/rustix/src/net/mod.rs @@ -0,0 +1,31 @@ +//! Network-related operations. +//! +//! On Windows, one must call [`wsa_startup`] in the process before calling any +//! of these APIs. [`wsa_cleanup`] may be used in the process if these APIs are +//! no longer needed. +//! +//! [`wsa_startup`]: https://docs.rs/rustix/*/x86_64-pc-windows-msvc/rustix/net/fn.wsa_startup.html +//! [`wsa_cleanup`]: https://docs.rs/rustix/*/x86_64-pc-windows-msvc/rustix/net/fn.wsa_cleanup.html + +mod send_recv; +mod socket; +mod socket_addr_any; +#[cfg(not(any(windows, target_os = "wasi")))] +mod socketpair; +mod types; +#[cfg(windows)] +mod wsa; + +pub mod sockopt; + +pub use crate::maybe_polyfill::net::{ +    IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, +}; +pub use send_recv::*; +pub use socket::*; +pub use socket_addr_any::{SocketAddrAny, SocketAddrStorage}; +#[cfg(not(any(windows, target_os = "wasi")))] +pub use socketpair::socketpair; +pub use types::*; +#[cfg(windows)] +pub use wsa::{wsa_cleanup, wsa_startup}; diff --git a/vendor/rustix/src/net/send_recv/mod.rs b/vendor/rustix/src/net/send_recv/mod.rs new file mode 100644 index 0000000..cad2d5c --- /dev/null +++ b/vendor/rustix/src/net/send_recv/mod.rs @@ -0,0 +1,380 @@ +//! `recv`, `send`, and variants. + +#![allow(unsafe_code)] + +use crate::buffer::split_init; +#[cfg(unix)] +use crate::net::SocketAddrUnix; +use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::{backend, io}; +use backend::fd::{AsFd, BorrowedFd}; +use core::mem::MaybeUninit; + +pub use backend::net::send_recv::{RecvFlags, SendFlags}; + +#[cfg(not(any( +    windows, +    target_os = "espidf", +    target_os = "redox", +    target_os = "vita", +    target_os = "wasi" +)))] +mod msg; + +#[cfg(not(any( +    windows, +    target_os = "espidf", +    target_os = "redox", +    target_os = "vita", +    target_os = "wasi" +)))] +pub use msg::*; + +/// `recv(fd, buf, flags)`—Reads data from a socket. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recv.2 +/// [OpenBSD]: https://man.openbsd.org/recv.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recv§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recv +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Data.html +#[inline] +pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> { +    unsafe { backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr(), buf.len(), flags) } +} + +/// `recv(fd, buf, flags)`—Reads data from a socket. +/// +/// This is equivalent to [`recv`], except that it can read into uninitialized +/// memory. It returns the slice that was initialized by this function and the +/// slice that remains uninitialized. +#[inline] +pub fn recv_uninit<Fd: AsFd>( +    fd: Fd, +    buf: &mut [MaybeUninit<u8>], +    flags: RecvFlags, +) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> { +    let length = unsafe { +        backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags) +    }; + +    Ok(unsafe { split_init(buf, length?) }) +} + +/// `send(fd, buf, flags)`—Writes data to a socket. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html +/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2 +/// [NetBSD]: https://man.netbsd.org/send.2 +/// [OpenBSD]: https://man.openbsd.org/send.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=send§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/send +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Data.html +#[inline] +pub fn send<Fd: AsFd>(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result<usize> { +    backend::net::syscalls::send(fd.as_fd(), buf, flags) +} + +/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and +/// returns the sender address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvfrom&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recvfrom.2 +/// [OpenBSD]: https://man.openbsd.org/recvfrom.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvfrom§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recvfrom +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Datagrams.html +#[inline] +pub fn recvfrom<Fd: AsFd>( +    fd: Fd, +    buf: &mut [u8], +    flags: RecvFlags, +) -> io::Result<(usize, Option<SocketAddrAny>)> { +    unsafe { backend::net::syscalls::recvfrom(fd.as_fd(), buf.as_mut_ptr(), buf.len(), flags) } +} + +/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and +/// returns the sender address. +/// +/// This is equivalent to [`recvfrom`], except that it can read into +/// uninitialized memory. It returns the slice that was initialized by this +/// function and the slice that remains uninitialized. +#[allow(clippy::type_complexity)] +#[inline] +pub fn recvfrom_uninit<Fd: AsFd>( +    fd: Fd, +    buf: &mut [MaybeUninit<u8>], +    flags: RecvFlags, +) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], Option<SocketAddrAny>)> { +    let (length, addr) = unsafe { +        backend::net::syscalls::recvfrom(fd.as_fd(), buf.as_mut_ptr() as *mut u8, buf.len(), flags)? +    }; +    let (init, uninit) = unsafe { split_init(buf, length) }; +    Ok((init, uninit, addr)) +} + +/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP +/// address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +pub fn sendto<Fd: AsFd>( +    fd: Fd, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddr, +) -> io::Result<usize> { +    _sendto(fd.as_fd(), buf, flags, addr) +} + +fn _sendto( +    fd: BorrowedFd<'_>, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddr, +) -> io::Result<usize> { +    match addr { +        SocketAddr::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), +        SocketAddr::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), +    } +} + +/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific +/// address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +pub fn sendto_any<Fd: AsFd>( +    fd: Fd, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddrAny, +) -> io::Result<usize> { +    _sendto_any(fd.as_fd(), buf, flags, addr) +} + +fn _sendto_any( +    fd: BorrowedFd<'_>, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddrAny, +) -> io::Result<usize> { +    match addr { +        SocketAddrAny::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), +        SocketAddrAny::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), +        #[cfg(unix)] +        SocketAddrAny::Unix(unix) => backend::net::syscalls::sendto_unix(fd, buf, flags, unix), +    } +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to +/// a socket to a specific IPv4 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_v4<Fd: AsFd>( +    fd: Fd, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddrV4, +) -> io::Result<usize> { +    backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr) +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data +/// to a socket to a specific IPv6 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_v6<Fd: AsFd>( +    fd: Fd, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddrV6, +) -> io::Result<usize> { +    backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr) +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to +/// a socket to a specific Unix-domain socket address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[cfg(unix)] +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_unix<Fd: AsFd>( +    fd: Fd, +    buf: &[u8], +    flags: SendFlags, +    addr: &SocketAddrUnix, +) -> io::Result<usize> { +    backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr) +} diff --git a/vendor/rustix/src/net/send_recv/msg.rs b/vendor/rustix/src/net/send_recv/msg.rs new file mode 100644 index 0000000..78fb865 --- /dev/null +++ b/vendor/rustix/src/net/send_recv/msg.rs @@ -0,0 +1,966 @@ +//! [`recvmsg`], [`sendmsg`], and related functions. + +#![allow(unsafe_code)] + +use crate::backend::{self, c}; +use crate::fd::{AsFd, BorrowedFd, OwnedFd}; +use crate::io::{self, IoSlice, IoSliceMut}; +#[cfg(linux_kernel)] +use crate::net::UCred; + +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::mem::{align_of, size_of, size_of_val, take}; +#[cfg(linux_kernel)] +use core::ptr::addr_of; +use core::{ptr, slice}; + +use super::{RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6}; + +/// Macro for defining the amount of space to allocate in a buffer for use with +/// [`RecvAncillaryBuffer::new`] and [`SendAncillaryBuffer::new`]. +/// +/// # Examples +/// +/// Allocate a buffer for a single file descriptor: +/// ``` +/// # use rustix::cmsg_space; +/// let mut space = [0; rustix::cmsg_space!(ScmRights(1))]; +/// ``` +/// +/// Allocate a buffer for credentials: +/// ``` +/// # #[cfg(linux_kernel)] +/// # { +/// # use rustix::cmsg_space; +/// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))]; +/// # } +/// ``` +/// +/// Allocate a buffer for two file descriptors and credentials: +/// ``` +/// # #[cfg(linux_kernel)] +/// # { +/// # use rustix::cmsg_space; +/// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))]; +/// # } +/// ``` +#[macro_export] +macro_rules! cmsg_space { +    // Base Rules +    (ScmRights($len:expr)) => { +        $crate::net::__cmsg_space( +            $len * ::core::mem::size_of::<$crate::fd::BorrowedFd<'static>>(), +        ) +    }; +    (ScmCredentials($len:expr)) => { +        $crate::net::__cmsg_space( +            $len * ::core::mem::size_of::<$crate::net::UCred>(), +        ) +    }; + +    // Combo Rules +    ($firstid:ident($firstex:expr), $($restid:ident($restex:expr)),*) => {{ +        // We only have to add `cmsghdr` alignment once; all other times we can +        // use `cmsg_aligned_space`. +        let sum = $crate::cmsg_space!($firstid($firstex)); +        $( +            let sum = sum + $crate::cmsg_aligned_space!($restid($restex)); +        )* +        sum +    }}; +} + +/// Like `cmsg_space`, but doesn't add padding for `cmsghdr` alignment. +#[doc(hidden)] +#[macro_export] +macro_rules! cmsg_aligned_space { +    // Base Rules +    (ScmRights($len:expr)) => { +        $crate::net::__cmsg_aligned_space( +            $len * ::core::mem::size_of::<$crate::fd::BorrowedFd<'static>>(), +        ) +    }; +    (ScmCredentials($len:expr)) => { +        $crate::net::__cmsg_aligned_space( +            $len * ::core::mem::size_of::<$crate::net::UCred>(), +        ) +    }; + +    // Combo Rules +    ($firstid:ident($firstex:expr), $($restid:ident($restex:expr)),*) => {{ +        let sum = cmsg_aligned_space!($firstid($firstex)); +        $( +            let sum = sum + cmsg_aligned_space!($restid($restex)); +        )* +        sum +    }}; +} + +#[doc(hidden)] +pub const fn __cmsg_space(len: usize) -> usize { +    // Add `align_of::<c::cmsghdr>()` so that we can align the user-provided +    // `&[u8]` to the required alignment boundary. +    let len = len + align_of::<c::cmsghdr>(); + +    __cmsg_aligned_space(len) +} + +#[doc(hidden)] +pub const fn __cmsg_aligned_space(len: usize) -> usize { +    // Convert `len` to `u32` for `CMSG_SPACE`. This would be `try_into()` if +    // we could call that in a `const fn`. +    let converted_len = len as u32; +    if converted_len as usize != len { +        unreachable!(); // `CMSG_SPACE` size overflow +    } + +    unsafe { c::CMSG_SPACE(converted_len) as usize } +} + +/// Ancillary message for [`sendmsg`], [`sendmsg_v4`], [`sendmsg_v6`], +/// [`sendmsg_unix`], and [`sendmsg_any`]. +#[non_exhaustive] +pub enum SendAncillaryMessage<'slice, 'fd> { +    /// Send file descriptors. +    #[doc(alias = "SCM_RIGHTS")] +    ScmRights(&'slice [BorrowedFd<'fd>]), +    /// Send process credentials. +    #[cfg(linux_kernel)] +    #[doc(alias = "SCM_CREDENTIAL")] +    ScmCredentials(UCred), +} + +impl SendAncillaryMessage<'_, '_> { +    /// Get the maximum size of an ancillary message. +    /// +    /// This can be helpful in determining the size of the buffer you allocate. +    pub const fn size(&self) -> usize { +        match self { +            Self::ScmRights(slice) => cmsg_space!(ScmRights(slice.len())), +            #[cfg(linux_kernel)] +            Self::ScmCredentials(_) => cmsg_space!(ScmCredentials(1)), +        } +    } +} + +/// Ancillary message for [`recvmsg`]. +#[non_exhaustive] +pub enum RecvAncillaryMessage<'a> { +    /// Received file descriptors. +    #[doc(alias = "SCM_RIGHTS")] +    ScmRights(AncillaryIter<'a, OwnedFd>), +    /// Received process credentials. +    #[cfg(linux_kernel)] +    #[doc(alias = "SCM_CREDENTIALS")] +    ScmCredentials(UCred), +} + +/// Buffer for sending ancillary messages with [`sendmsg`], [`sendmsg_v4`], +/// [`sendmsg_v6`], [`sendmsg_unix`], and [`sendmsg_any`]. +/// +/// Use the [`push`] function to add messages to send. +/// +/// [`push`]: SendAncillaryBuffer::push +pub struct SendAncillaryBuffer<'buf, 'slice, 'fd> { +    /// Raw byte buffer for messages. +    buffer: &'buf mut [u8], + +    /// The amount of the buffer that is used. +    length: usize, + +    /// Phantom data for lifetime of `&'slice [BorrowedFd<'fd>]`. +    _phantom: PhantomData<&'slice [BorrowedFd<'fd>]>, +} + +impl<'buf> From<&'buf mut [u8]> for SendAncillaryBuffer<'buf, '_, '_> { +    fn from(buffer: &'buf mut [u8]) -> Self { +        Self::new(buffer) +    } +} + +impl Default for SendAncillaryBuffer<'_, '_, '_> { +    fn default() -> Self { +        Self { +            buffer: &mut [], +            length: 0, +            _phantom: PhantomData, +        } +    } +} + +impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> { +    /// Create a new, empty `SendAncillaryBuffer` from a raw byte buffer. +    /// +    /// The buffer size may be computed with [`cmsg_space`], or it may be +    /// zero for an empty buffer, however in that case, consider `default()` +    /// instead, or even using [`send`] instead of `sendmsg`. +    /// +    /// # Examples +    /// +    /// Allocate a buffer for a single file descriptor: +    /// ``` +    /// # use rustix::cmsg_space; +    /// # use rustix::net::SendAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))]; +    /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space); +    /// ``` +    /// +    /// Allocate a buffer for credentials: +    /// ``` +    /// # #[cfg(linux_kernel)] +    /// # { +    /// # use rustix::cmsg_space; +    /// # use rustix::net::SendAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))]; +    /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space); +    /// # } +    /// ``` +    /// +    /// Allocate a buffer for two file descriptors and credentials: +    /// ``` +    /// # #[cfg(linux_kernel)] +    /// # { +    /// # use rustix::cmsg_space; +    /// # use rustix::net::SendAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))]; +    /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space); +    /// # } +    /// ``` +    /// +    /// [`send`]: crate::net::send +    #[inline] +    pub fn new(buffer: &'buf mut [u8]) -> Self { +        Self { +            buffer: align_for_cmsghdr(buffer), +            length: 0, +            _phantom: PhantomData, +        } +    } + +    /// Returns a pointer to the message data. +    pub(crate) fn as_control_ptr(&mut self) -> *mut u8 { +        // When the length is zero, we may be using a `&[]` address, which may +        // be an invalid but non-null pointer, and on some platforms, that +        // causes `sendmsg` to fail with `EFAULT` or `EINVAL` +        #[cfg(not(linux_kernel))] +        if self.length == 0 { +            return core::ptr::null_mut(); +        } + +        self.buffer.as_mut_ptr() +    } + +    /// Returns the length of the message data. +    pub(crate) fn control_len(&self) -> usize { +        self.length +    } + +    /// Delete all messages from the buffer. +    pub fn clear(&mut self) { +        self.length = 0; +    } + +    /// Add an ancillary message to the buffer. +    /// +    /// Returns `true` if the message was added successfully. +    pub fn push(&mut self, msg: SendAncillaryMessage<'slice, 'fd>) -> bool { +        match msg { +            SendAncillaryMessage::ScmRights(fds) => { +                let fds_bytes = +                    unsafe { slice::from_raw_parts(fds.as_ptr().cast::<u8>(), size_of_val(fds)) }; +                self.push_ancillary(fds_bytes, c::SOL_SOCKET as _, c::SCM_RIGHTS as _) +            } +            #[cfg(linux_kernel)] +            SendAncillaryMessage::ScmCredentials(ucred) => { +                let ucred_bytes = unsafe { +                    slice::from_raw_parts(addr_of!(ucred).cast::<u8>(), size_of_val(&ucred)) +                }; +                self.push_ancillary(ucred_bytes, c::SOL_SOCKET as _, c::SCM_CREDENTIALS as _) +            } +        } +    } + +    /// Pushes an ancillary message to the buffer. +    fn push_ancillary(&mut self, source: &[u8], cmsg_level: c::c_int, cmsg_type: c::c_int) -> bool { +        macro_rules! leap { +            ($e:expr) => {{ +                match ($e) { +                    Some(x) => x, +                    None => return false, +                } +            }}; +        } + +        // Calculate the length of the message. +        let source_len = leap!(u32::try_from(source.len()).ok()); + +        // Calculate the new length of the buffer. +        let additional_space = unsafe { c::CMSG_SPACE(source_len) }; +        let new_length = leap!(self.length.checked_add(additional_space as usize)); +        let buffer = leap!(self.buffer.get_mut(..new_length)); + +        // Fill the new part of the buffer with zeroes. +        buffer[self.length..new_length].fill(0); +        self.length = new_length; + +        // Get the last header in the buffer. +        let last_header = leap!(messages::Messages::new(buffer).last()); + +        // Set the header fields. +        last_header.cmsg_len = unsafe { c::CMSG_LEN(source_len) } as _; +        last_header.cmsg_level = cmsg_level; +        last_header.cmsg_type = cmsg_type; + +        // Get the pointer to the payload and copy the data. +        unsafe { +            let payload = c::CMSG_DATA(last_header); +            ptr::copy_nonoverlapping(source.as_ptr(), payload, source_len as _); +        } + +        true +    } +} + +impl<'slice, 'fd> Extend<SendAncillaryMessage<'slice, 'fd>> +    for SendAncillaryBuffer<'_, 'slice, 'fd> +{ +    fn extend<T: IntoIterator<Item = SendAncillaryMessage<'slice, 'fd>>>(&mut self, iter: T) { +        // TODO: This could be optimized to add every message in one go. +        iter.into_iter().all(|msg| self.push(msg)); +    } +} + +/// Buffer for receiving ancillary messages with [`recvmsg`]. +/// +/// Use the [`drain`] function to iterate over the received messages. +/// +/// [`drain`]: RecvAncillaryBuffer::drain +#[derive(Default)] +pub struct RecvAncillaryBuffer<'buf> { +    /// Raw byte buffer for messages. +    buffer: &'buf mut [u8], + +    /// The portion of the buffer we've read from already. +    read: usize, + +    /// The amount of the buffer that is used. +    length: usize, +} + +impl<'buf> From<&'buf mut [u8]> for RecvAncillaryBuffer<'buf> { +    fn from(buffer: &'buf mut [u8]) -> Self { +        Self::new(buffer) +    } +} + +impl<'buf> RecvAncillaryBuffer<'buf> { +    /// Create a new, empty `RecvAncillaryBuffer` from a raw byte buffer. +    /// +    /// The buffer size may be computed with [`cmsg_space`], or it may be +    /// zero for an empty buffer, however in that case, consider `default()` +    /// instead, or even using [`recv`] instead of `recvmsg`. +    /// +    /// # Examples +    /// +    /// Allocate a buffer for a single file descriptor: +    /// ``` +    /// # use rustix::cmsg_space; +    /// # use rustix::net::RecvAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))]; +    /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space); +    /// ``` +    /// +    /// Allocate a buffer for credentials: +    /// ``` +    /// # #[cfg(linux_kernel)] +    /// # { +    /// # use rustix::cmsg_space; +    /// # use rustix::net::RecvAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))]; +    /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space); +    /// # } +    /// ``` +    /// +    /// Allocate a buffer for two file descriptors and credentials: +    /// ``` +    /// # #[cfg(linux_kernel)] +    /// # { +    /// # use rustix::cmsg_space; +    /// # use rustix::net::RecvAncillaryBuffer; +    /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))]; +    /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space); +    /// # } +    /// ``` +    /// +    /// [`recv`]: crate::net::recv +    #[inline] +    pub fn new(buffer: &'buf mut [u8]) -> Self { +        Self { +            buffer: align_for_cmsghdr(buffer), +            read: 0, +            length: 0, +        } +    } + +    /// Returns a pointer to the message data. +    pub(crate) fn as_control_ptr(&mut self) -> *mut u8 { +        // When the length is zero, we may be using a `&[]` address, which may +        // be an invalid but non-null pointer, and on some platforms, that +        // causes `sendmsg` to fail with `EFAULT` or `EINVAL` +        #[cfg(not(linux_kernel))] +        if self.buffer.is_empty() { +            return core::ptr::null_mut(); +        } + +        self.buffer.as_mut_ptr() +    } + +    /// Returns the length of the message data. +    pub(crate) fn control_len(&self) -> usize { +        self.buffer.len() +    } + +    /// Set the length of the message data. +    /// +    /// # Safety +    /// +    /// The buffer must be filled with valid message data. +    pub(crate) unsafe fn set_control_len(&mut self, len: usize) { +        self.length = len; +        self.read = 0; +    } + +    /// Delete all messages from the buffer. +    pub(crate) fn clear(&mut self) { +        self.drain().for_each(drop); +    } + +    /// Drain all messages from the buffer. +    pub fn drain(&mut self) -> AncillaryDrain<'_> { +        AncillaryDrain { +            messages: messages::Messages::new(&mut self.buffer[self.read..][..self.length]), +            read: &mut self.read, +            length: &mut self.length, +        } +    } +} + +impl Drop for RecvAncillaryBuffer<'_> { +    fn drop(&mut self) { +        self.clear(); +    } +} + +/// Return a slice of `buffer` starting at the first `cmsghdr` alignment +/// boundary. +#[inline] +fn align_for_cmsghdr(buffer: &mut [u8]) -> &mut [u8] { +    // If the buffer is empty, we won't be writing anything into it, so it +    // doesn't need to be aligned. +    if buffer.is_empty() { +        return buffer; +    } + +    let align = align_of::<c::cmsghdr>(); +    let addr = buffer.as_ptr() as usize; +    let adjusted = (addr + (align - 1)) & align.wrapping_neg(); +    &mut buffer[adjusted - addr..] +} + +/// An iterator that drains messages from a [`RecvAncillaryBuffer`]. +pub struct AncillaryDrain<'buf> { +    /// Inner iterator over messages. +    messages: messages::Messages<'buf>, + +    /// Increment the number of messages we've read. +    read: &'buf mut usize, + +    /// Decrement the total length. +    length: &'buf mut usize, +} + +impl<'buf> AncillaryDrain<'buf> { +    /// A closure that converts a message into a [`RecvAncillaryMessage`]. +    fn cvt_msg( +        read: &mut usize, +        length: &mut usize, +        msg: &c::cmsghdr, +    ) -> Option<RecvAncillaryMessage<'buf>> { +        unsafe { +            // Advance the `read` pointer. +            let msg_len = msg.cmsg_len as usize; +            *read += msg_len; +            *length -= msg_len; + +            // Get a pointer to the payload. +            let payload = c::CMSG_DATA(msg); +            let payload_len = msg.cmsg_len as usize - c::CMSG_LEN(0) as usize; + +            // Get a mutable slice of the payload. +            let payload: &'buf mut [u8] = slice::from_raw_parts_mut(payload, payload_len); + +            // Determine what type it is. +            let (level, msg_type) = (msg.cmsg_level, msg.cmsg_type); +            match (level as _, msg_type as _) { +                (c::SOL_SOCKET, c::SCM_RIGHTS) => { +                    // Create an iterator that reads out the file descriptors. +                    let fds = AncillaryIter::new(payload); + +                    Some(RecvAncillaryMessage::ScmRights(fds)) +                } +                #[cfg(linux_kernel)] +                (c::SOL_SOCKET, c::SCM_CREDENTIALS) => { +                    if payload_len >= size_of::<UCred>() { +                        let ucred = payload.as_ptr().cast::<UCred>().read_unaligned(); +                        Some(RecvAncillaryMessage::ScmCredentials(ucred)) +                    } else { +                        None +                    } +                } +                _ => None, +            } +        } +    } +} + +impl<'buf> Iterator for AncillaryDrain<'buf> { +    type Item = RecvAncillaryMessage<'buf>; + +    fn next(&mut self) -> Option<Self::Item> { +        let read = &mut self.read; +        let length = &mut self.length; +        self.messages.find_map(|ev| Self::cvt_msg(read, length, ev)) +    } + +    fn size_hint(&self) -> (usize, Option<usize>) { +        let (_, max) = self.messages.size_hint(); +        (0, max) +    } + +    fn fold<B, F>(self, init: B, f: F) -> B +    where +        Self: Sized, +        F: FnMut(B, Self::Item) -> B, +    { +        let read = self.read; +        let length = self.length; +        self.messages +            .filter_map(|ev| Self::cvt_msg(read, length, ev)) +            .fold(init, f) +    } + +    fn count(self) -> usize { +        let read = self.read; +        let length = self.length; +        self.messages +            .filter_map(|ev| Self::cvt_msg(read, length, ev)) +            .count() +    } + +    fn last(self) -> Option<Self::Item> +    where +        Self: Sized, +    { +        let read = self.read; +        let length = self.length; +        self.messages +            .filter_map(|ev| Self::cvt_msg(read, length, ev)) +            .last() +    } + +    fn collect<B: FromIterator<Self::Item>>(self) -> B +    where +        Self: Sized, +    { +        let read = self.read; +        let length = self.length; +        self.messages +            .filter_map(|ev| Self::cvt_msg(read, length, ev)) +            .collect() +    } +} + +impl FusedIterator for AncillaryDrain<'_> {} + +/// `sendmsg(msghdr)`—Sends a message on a socket. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg( +    socket: impl AsFd, +    iov: &[IoSlice<'_>], +    control: &mut SendAncillaryBuffer<'_, '_, '_>, +    flags: SendFlags, +) -> io::Result<usize> { +    backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv4 address. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_v4( +    socket: impl AsFd, +    addr: &SocketAddrV4, +    iov: &[IoSlice<'_>], +    control: &mut SendAncillaryBuffer<'_, '_, '_>, +    flags: SendFlags, +) -> io::Result<usize> { +    backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv6 address. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_v6( +    socket: impl AsFd, +    addr: &SocketAddrV6, +    iov: &[IoSlice<'_>], +    control: &mut SendAncillaryBuffer<'_, '_, '_>, +    flags: SendFlags, +) -> io::Result<usize> { +    backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific Unix-domain +/// address. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +#[cfg(unix)] +pub fn sendmsg_unix( +    socket: impl AsFd, +    addr: &super::SocketAddrUnix, +    iov: &[IoSlice<'_>], +    control: &mut SendAncillaryBuffer<'_, '_, '_>, +    flags: SendFlags, +) -> io::Result<usize> { +    backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific address. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_any( +    socket: impl AsFd, +    addr: Option<&SocketAddrAny>, +    iov: &[IoSlice<'_>], +    control: &mut SendAncillaryBuffer<'_, '_, '_>, +    flags: SendFlags, +) -> io::Result<usize> { +    match addr { +        None => backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags), +        Some(SocketAddrAny::V4(addr)) => { +            backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags) +        } +        Some(SocketAddrAny::V6(addr)) => { +            backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags) +        } +        #[cfg(unix)] +        Some(SocketAddrAny::Unix(addr)) => { +            backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags) +        } +    } +} + +/// `recvmsg(msghdr)`—Receives a message from a socket. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recvmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recvmsg.2 +/// [OpenBSD]: https://man.openbsd.org/recvmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recvmsg +#[inline] +pub fn recvmsg( +    socket: impl AsFd, +    iov: &mut [IoSliceMut<'_>], +    control: &mut RecvAncillaryBuffer<'_>, +    flags: RecvFlags, +) -> io::Result<RecvMsgReturn> { +    backend::net::syscalls::recvmsg(socket.as_fd(), iov, control, flags) +} + +/// The result of a successful [`recvmsg`] call. +pub struct RecvMsgReturn { +    /// The number of bytes received. +    pub bytes: usize, + +    /// The flags received. +    pub flags: RecvFlags, + +    /// The address of the socket we received from, if any. +    pub address: Option<SocketAddrAny>, +} + +/// An iterator over data in an ancillary buffer. +pub struct AncillaryIter<'data, T> { +    /// The data we're iterating over. +    data: &'data mut [u8], + +    /// The raw data we're removing. +    _marker: PhantomData<T>, +} + +impl<'data, T> AncillaryIter<'data, T> { +    /// Create a new iterator over data in an ancillary buffer. +    /// +    /// # Safety +    /// +    /// The buffer must contain valid ancillary data. +    unsafe fn new(data: &'data mut [u8]) -> Self { +        assert_eq!(data.len() % size_of::<T>(), 0); + +        Self { +            data, +            _marker: PhantomData, +        } +    } +} + +impl<'data, T> Drop for AncillaryIter<'data, T> { +    fn drop(&mut self) { +        self.for_each(drop); +    } +} + +impl<T> Iterator for AncillaryIter<'_, T> { +    type Item = T; + +    fn next(&mut self) -> Option<Self::Item> { +        // See if there is a next item. +        if self.data.len() < size_of::<T>() { +            return None; +        } + +        // Get the next item. +        let item = unsafe { self.data.as_ptr().cast::<T>().read_unaligned() }; + +        // Move forward. +        let data = take(&mut self.data); +        self.data = &mut data[size_of::<T>()..]; + +        Some(item) +    } + +    fn size_hint(&self) -> (usize, Option<usize>) { +        let len = self.len(); +        (len, Some(len)) +    } + +    fn count(self) -> usize { +        self.len() +    } + +    fn last(mut self) -> Option<Self::Item> { +        self.next_back() +    } +} + +impl<T> FusedIterator for AncillaryIter<'_, T> {} + +impl<T> ExactSizeIterator for AncillaryIter<'_, T> { +    fn len(&self) -> usize { +        self.data.len() / size_of::<T>() +    } +} + +impl<T> DoubleEndedIterator for AncillaryIter<'_, T> { +    fn next_back(&mut self) -> Option<Self::Item> { +        // See if there is a next item. +        if self.data.len() < size_of::<T>() { +            return None; +        } + +        // Get the next item. +        let item = unsafe { +            let ptr = self.data.as_ptr().add(self.data.len() - size_of::<T>()); +            ptr.cast::<T>().read_unaligned() +        }; + +        // Move forward. +        let len = self.data.len(); +        let data = take(&mut self.data); +        self.data = &mut data[..len - size_of::<T>()]; + +        Some(item) +    } +} + +mod messages { +    use crate::backend::c; +    use crate::backend::net::msghdr; +    use core::iter::FusedIterator; +    use core::marker::PhantomData; +    use core::ptr::NonNull; + +    /// An iterator over the messages in an ancillary buffer. +    pub(super) struct Messages<'buf> { +        /// The message header we're using to iterate over the messages. +        msghdr: c::msghdr, + +        /// The current pointer to the next message header to return. +        /// +        /// This has a lifetime of `'buf`. +        header: Option<NonNull<c::cmsghdr>>, + +        /// Capture the original lifetime of the buffer. +        _buffer: PhantomData<&'buf mut [u8]>, +    } + +    impl<'buf> Messages<'buf> { +        /// Create a new iterator over messages from a byte buffer. +        pub(super) fn new(buf: &'buf mut [u8]) -> Self { +            let msghdr = { +                let mut h = msghdr::zero_msghdr(); +                h.msg_control = buf.as_mut_ptr().cast(); +                h.msg_controllen = buf.len().try_into().expect("buffer too large for msghdr"); +                h +            }; + +            // Get the first header. +            let header = NonNull::new(unsafe { c::CMSG_FIRSTHDR(&msghdr) }); + +            Self { +                msghdr, +                header, +                _buffer: PhantomData, +            } +        } +    } + +    impl<'a> Iterator for Messages<'a> { +        type Item = &'a mut c::cmsghdr; + +        #[inline] +        fn next(&mut self) -> Option<Self::Item> { +            // Get the current header. +            let header = self.header?; + +            // Get the next header. +            self.header = NonNull::new(unsafe { c::CMSG_NXTHDR(&self.msghdr, header.as_ptr()) }); + +            // If the headers are equal, we're done. +            if Some(header) == self.header { +                self.header = None; +            } + +            // SAFETY: The lifetime of `header` is tied to this. +            Some(unsafe { &mut *header.as_ptr() }) +        } + +        fn size_hint(&self) -> (usize, Option<usize>) { +            if self.header.is_some() { +                // The remaining buffer *could* be filled with zero-length +                // messages. +                let max_size = unsafe { c::CMSG_LEN(0) } as usize; +                let remaining_count = self.msghdr.msg_controllen as usize / max_size; +                (1, Some(remaining_count)) +            } else { +                (0, Some(0)) +            } +        } +    } + +    impl FusedIterator for Messages<'_> {} +} diff --git a/vendor/rustix/src/net/socket.rs b/vendor/rustix/src/net/socket.rs new file mode 100644 index 0000000..c01b7a4 --- /dev/null +++ b/vendor/rustix/src/net/socket.rs @@ -0,0 +1,750 @@ +use crate::fd::OwnedFd; +use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::{backend, io}; +use backend::fd::{AsFd, BorrowedFd}; + +pub use crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; +#[cfg(unix)] +pub use backend::net::addr::SocketAddrUnix; + +/// `socket(domain, type_, protocol)`—Creates a socket. +/// +/// POSIX guarantees that `socket` will use the lowest unused file descriptor, +/// however it is not safe in general to rely on this, as file descriptors may +/// be unexpectedly allocated on other threads or in libraries. +/// +/// To pass extra flags such as [`SocketFlags::CLOEXEC`] or +/// [`SocketFlags::NONBLOCK`], use [`socket_with`]. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#socket +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html +/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=socket&sektion=2 +/// [NetBSD]: https://man.netbsd.org/socket.2 +/// [OpenBSD]: https://man.openbsd.org/socket.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=socket§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/socket +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Creating-a-Socket.html +#[inline] +pub fn socket( +    domain: AddressFamily, +    type_: SocketType, +    protocol: Option<Protocol>, +) -> io::Result<OwnedFd> { +    backend::net::syscalls::socket(domain, type_, protocol) +} + +/// `socket_with(domain, type_ | flags, protocol)`—Creates a socket, with +/// flags. +/// +/// POSIX guarantees that `socket` will use the lowest unused file descriptor, +/// however it is not safe in general to rely on this, as file descriptors may +/// be unexpectedly allocated on other threads or in libraries. +/// +/// `socket_with` is the same as [`socket`] but adds an additional flags +/// operand. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#socket +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html +/// [Linux]: https://man7.org/linux/man-pages/man2/socket.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socket.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=socket&sektion=2 +/// [NetBSD]: https://man.netbsd.org/socket.2 +/// [OpenBSD]: https://man.openbsd.org/socket.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=socket§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/socket +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Creating-a-Socket.html +#[doc(alias("socket"))] +#[inline] +pub fn socket_with( +    domain: AddressFamily, +    type_: SocketType, +    flags: SocketFlags, +    protocol: Option<Protocol>, +) -> io::Result<OwnedFd> { +    backend::net::syscalls::socket_with(domain, type_, flags, protocol) +} + +/// `bind(sockfd, addr)`—Binds a socket to an IP address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html +/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2 +/// [NetBSD]: https://man.netbsd.org/bind.2 +/// [OpenBSD]: https://man.openbsd.org/bind.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/bind +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Setting-Address.html +pub fn bind<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> { +    _bind(sockfd.as_fd(), addr) +} + +fn _bind(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> { +    match addr { +        SocketAddr::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4), +        SocketAddr::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6), +    } +} + +/// `bind(sockfd, addr)`—Binds a socket to an address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html +/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2 +/// [NetBSD]: https://man.netbsd.org/bind.2 +/// [OpenBSD]: https://man.openbsd.org/bind.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/bind +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Setting-Address.html +#[doc(alias = "bind")] +pub fn bind_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> { +    _bind_any(sockfd.as_fd(), addr) +} + +fn _bind_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> { +    match addr { +        SocketAddrAny::V4(v4) => backend::net::syscalls::bind_v4(sockfd, v4), +        SocketAddrAny::V6(v6) => backend::net::syscalls::bind_v6(sockfd, v6), +        #[cfg(unix)] +        SocketAddrAny::Unix(unix) => backend::net::syscalls::bind_unix(sockfd, unix), +    } +} + +/// `bind(sockfd, addr, sizeof(struct sockaddr_in))`—Binds a socket to an +/// IPv4 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html +/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2 +/// [NetBSD]: https://man.netbsd.org/bind.2 +/// [OpenBSD]: https://man.openbsd.org/bind.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/bind +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Setting-Address.html +#[inline] +#[doc(alias = "bind")] +pub fn bind_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { +    backend::net::syscalls::bind_v4(sockfd.as_fd(), addr) +} + +/// `bind(sockfd, addr, sizeof(struct sockaddr_in6))`—Binds a socket to an +/// IPv6 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html +/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2 +/// [NetBSD]: https://man.netbsd.org/bind.2 +/// [OpenBSD]: https://man.openbsd.org/bind.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/bind +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Setting-Address.html +#[inline] +#[doc(alias = "bind")] +pub fn bind_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { +    backend::net::syscalls::bind_v6(sockfd.as_fd(), addr) +} + +/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a +/// Unix-domain address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#bind +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html +/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/bind.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=bind&sektion=2 +/// [NetBSD]: https://man.netbsd.org/bind.2 +/// [OpenBSD]: https://man.openbsd.org/bind.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/bind +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Setting-Address.html +#[cfg(unix)] +#[inline] +#[doc(alias = "bind")] +pub fn bind_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { +    backend::net::syscalls::bind_unix(sockfd.as_fd(), addr) +} + +/// `connect(sockfd, addr)`—Initiates a connection to an IP address. +/// +/// On Windows, a non-blocking socket returns [`Errno::WOULDBLOCK`] if the +/// connection cannot be completed immediately, rather than +/// `Errno::INPROGRESS`. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +/// [`Errno::WOULDBLOCK`]: io::Errno::WOULDBLOCK +pub fn connect<Fd: AsFd>(sockfd: Fd, addr: &SocketAddr) -> io::Result<()> { +    _connect(sockfd.as_fd(), addr) +} + +fn _connect(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> { +    match addr { +        SocketAddr::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4), +        SocketAddr::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6), +    } +} + +/// `connect(sockfd, addr)`—Initiates a connection. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +#[doc(alias = "connect")] +pub fn connect_any<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> { +    _connect_any(sockfd.as_fd(), addr) +} + +fn _connect_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> { +    match addr { +        SocketAddrAny::V4(v4) => backend::net::syscalls::connect_v4(sockfd, v4), +        SocketAddrAny::V6(v6) => backend::net::syscalls::connect_v6(sockfd, v6), +        #[cfg(unix)] +        SocketAddrAny::Unix(unix) => backend::net::syscalls::connect_unix(sockfd, unix), +    } +} + +/// `connect(sockfd, addr, sizeof(struct sockaddr_in))`—Initiates a +/// connection to an IPv4 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +#[inline] +#[doc(alias = "connect")] +pub fn connect_v4<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { +    backend::net::syscalls::connect_v4(sockfd.as_fd(), addr) +} + +/// `connect(sockfd, addr, sizeof(struct sockaddr_in6))`—Initiates a +/// connection to an IPv6 address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +#[inline] +#[doc(alias = "connect")] +pub fn connect_v6<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { +    backend::net::syscalls::connect_v6(sockfd.as_fd(), addr) +} + +/// `connect(sockfd, addr, sizeof(struct sockaddr_un))`—Initiates a +/// connection to a Unix-domain address. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +#[cfg(unix)] +#[inline] +#[doc(alias = "connect")] +pub fn connect_unix<Fd: AsFd>(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { +    backend::net::syscalls::connect_unix(sockfd.as_fd(), addr) +} + +/// `connect(sockfd, {.sa_family = AF_UNSPEC}, sizeof(struct sockaddr))` +/// — Dissolve the socket's association. +/// +/// On UDP sockets, BSD platforms report [`Errno::AFNOSUPPORT`] or +/// [`Errno::INVAL`] even if the disconnect was successful. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#connect +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html +/// [Linux]: https://man7.org/linux/man-pages/man2/connect.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/connect.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=connect&sektion=2 +/// [NetBSD]: https://man.netbsd.org/connect.2 +/// [OpenBSD]: https://man.openbsd.org/connect.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=connect§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/connect +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Connecting.html +/// [`Errno::AFNOSUPPORT`]: io::Errno::AFNOSUPPORT +/// [`Errno::INVAL`]: io::Errno::INVAL +#[inline] +#[doc(alias = "connect")] +pub fn connect_unspec<Fd: AsFd>(sockfd: Fd) -> io::Result<()> { +    backend::net::syscalls::connect_unspec(sockfd.as_fd()) +} + +/// `listen(fd, backlog)`—Enables listening for incoming connections. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#listen +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html +/// [Linux]: https://man7.org/linux/man-pages/man2/listen.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listen.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=listen&sektion=2 +/// [NetBSD]: https://man.netbsd.org/listen.2 +/// [OpenBSD]: https://man.openbsd.org/listen.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=listen§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/listen +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Listening.html +#[inline] +pub fn listen<Fd: AsFd>(sockfd: Fd, backlog: i32) -> io::Result<()> { +    backend::net::syscalls::listen(sockfd.as_fd(), backlog) +} + +/// `accept(fd, NULL, NULL)`—Accepts an incoming connection. +/// +/// Use [`acceptfrom`] to retrieve the peer address. +/// +/// POSIX guarantees that `accept` will use the lowest unused file descriptor, +/// however it is not safe in general to rely on this, as file descriptors may +/// be unexpectedly allocated on other threads or in libraries. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#acceptthank-you-for-calling-port-3490. +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html +/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=accept&sektion=2 +/// [NetBSD]: https://man.netbsd.org/accept.2 +/// [OpenBSD]: https://man.openbsd.org/accept.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=accept§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/accept +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Accepting-Connections.html +#[inline] +pub fn accept<Fd: AsFd>(sockfd: Fd) -> io::Result<OwnedFd> { +    backend::net::syscalls::accept(sockfd.as_fd()) +} + +/// `accept4(fd, NULL, NULL, flags)`—Accepts an incoming connection, with +/// flags. +/// +/// Use [`acceptfrom_with`] to retrieve the peer address. +/// +/// Even though POSIX guarantees that this will use the lowest unused file +/// descriptor, it is not safe in general to rely on this, as file descriptors +/// may be unexpectedly allocated on other threads or in libraries. +/// +/// `accept_with` is the same as [`accept`] but adds an additional flags +/// operand. +/// +/// # References +///  - [Linux] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=accept4&sektion=2 +/// [NetBSD]: https://man.netbsd.org/accept4.2 +/// [OpenBSD]: https://man.openbsd.org/accept4.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=accept4§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/accept4 +#[inline] +#[doc(alias = "accept4")] +pub fn accept_with<Fd: AsFd>(sockfd: Fd, flags: SocketFlags) -> io::Result<OwnedFd> { +    backend::net::syscalls::accept_with(sockfd.as_fd(), flags) +} + +/// `accept(fd, &addr, &len)`—Accepts an incoming connection and returns the +/// peer address. +/// +/// Use [`accept`] if the peer address isn't needed. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#acceptthank-you-for-calling-port-3490. +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html +/// [Linux]: https://man7.org/linux/man-pages/man2/accept.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/accept.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=accept&sektion=2 +/// [NetBSD]: https://man.netbsd.org/accept.2 +/// [OpenBSD]: https://man.openbsd.org/accept.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=accept§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/accept +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Accepting-Connections.html +#[inline] +#[doc(alias = "accept")] +pub fn acceptfrom<Fd: AsFd>(sockfd: Fd) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> { +    backend::net::syscalls::acceptfrom(sockfd.as_fd()) +} + +/// `accept4(fd, &addr, &len, flags)`—Accepts an incoming connection and +/// returns the peer address, with flags. +/// +/// Use [`accept_with`] if the peer address isn't needed. +/// +/// `acceptfrom_with` is the same as [`acceptfrom`] but adds an additional +/// flags operand. +/// +/// # References +///  - [Linux] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/accept4.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=accept4&sektion=2 +/// [NetBSD]: https://man.netbsd.org/accept4.2 +/// [OpenBSD]: https://man.openbsd.org/accept4.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=accept4§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/accept4 +#[inline] +#[doc(alias = "accept4")] +pub fn acceptfrom_with<Fd: AsFd>( +    sockfd: Fd, +    flags: SocketFlags, +) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> { +    backend::net::syscalls::acceptfrom_with(sockfd.as_fd(), flags) +} + +/// `shutdown(fd, how)`—Closes the read and/or write sides of a stream. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#close-and-shutdownget-outta-my-face +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html +/// [Linux]: https://man7.org/linux/man-pages/man2/shutdown.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shutdown.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=shutdown&sektion=2 +/// [NetBSD]: https://man.netbsd.org/shutdown.2 +/// [OpenBSD]: https://man.openbsd.org/shutdown.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=shutdown§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/shutdown +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Closing-a-Socket.html +#[inline] +pub fn shutdown<Fd: AsFd>(sockfd: Fd, how: Shutdown) -> io::Result<()> { +    backend::net::syscalls::shutdown(sockfd.as_fd(), how) +} + +/// `getsockname(fd, addr, len)`—Returns the address a socket is bound to. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html +/// [Linux]: https://man7.org/linux/man-pages/man2/getsockname.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockname.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockname +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getsockname&sektion=2 +/// [NetBSD]: https://man.netbsd.org/getsockname.2 +/// [OpenBSD]: https://man.openbsd.org/getsockname.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getsockname§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/getsockname +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Reading-Address.html +#[inline] +pub fn getsockname<Fd: AsFd>(sockfd: Fd) -> io::Result<SocketAddrAny> { +    backend::net::syscalls::getsockname(sockfd.as_fd()) +} + +/// `getpeername(fd, addr, len)`—Returns the address a socket is connected +/// to. +/// +/// # References +///  - [Beej's Guide to Network Programming] +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [Winsock] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#getpeernamewho-are-you +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html +/// [Linux]: https://man7.org/linux/man-pages/man2/getpeername.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpeername.2.html +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getpeername +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=getpeername&sektion=2 +/// [NetBSD]: https://man.netbsd.org/getpeername.2 +/// [OpenBSD]: https://man.openbsd.org/getpeername.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=getpeername§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/getpeername +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Who-is-Connected.html +#[inline] +pub fn getpeername<Fd: AsFd>(sockfd: Fd) -> io::Result<Option<SocketAddrAny>> { +    backend::net::syscalls::getpeername(sockfd.as_fd()) +} diff --git a/vendor/rustix/src/net/socket_addr_any.rs b/vendor/rustix/src/net/socket_addr_any.rs new file mode 100644 index 0000000..a649015 --- /dev/null +++ b/vendor/rustix/src/net/socket_addr_any.rs @@ -0,0 +1,113 @@ +//! A socket address for any kind of socket. +//! +//! This is similar to [`std::net::SocketAddr`], but also supports Unix-domain +//! socket addresses on Unix. +//! +//! # Safety +//! +//! The `read` and `write` functions allow decoding and encoding from and to +//! OS-specific socket address representations in memory. +#![allow(unsafe_code)] + +#[cfg(unix)] +use crate::net::SocketAddrUnix; +use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::{backend, io}; +#[cfg(feature = "std")] +use core::fmt; + +pub use backend::net::addr::SocketAddrStorage; + +/// `struct sockaddr_storage` as a Rust enum. +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[doc(alias = "sockaddr")] +#[non_exhaustive] +pub enum SocketAddrAny { +    /// `struct sockaddr_in` +    V4(SocketAddrV4), +    /// `struct sockaddr_in6` +    V6(SocketAddrV6), +    /// `struct sockaddr_un` +    #[cfg(unix)] +    Unix(SocketAddrUnix), +} + +impl From<SocketAddr> for SocketAddrAny { +    #[inline] +    fn from(from: SocketAddr) -> Self { +        match from { +            SocketAddr::V4(v4) => Self::V4(v4), +            SocketAddr::V6(v6) => Self::V6(v6), +        } +    } +} + +impl From<SocketAddrV4> for SocketAddrAny { +    #[inline] +    fn from(from: SocketAddrV4) -> Self { +        Self::V4(from) +    } +} + +impl From<SocketAddrV6> for SocketAddrAny { +    #[inline] +    fn from(from: SocketAddrV6) -> Self { +        Self::V6(from) +    } +} + +#[cfg(unix)] +impl From<SocketAddrUnix> for SocketAddrAny { +    #[inline] +    fn from(from: SocketAddrUnix) -> Self { +        Self::Unix(from) +    } +} + +impl SocketAddrAny { +    /// Return the address family of this socket address. +    #[inline] +    pub const fn address_family(&self) -> AddressFamily { +        match self { +            Self::V4(_) => AddressFamily::INET, +            Self::V6(_) => AddressFamily::INET6, +            #[cfg(unix)] +            Self::Unix(_) => AddressFamily::UNIX, +        } +    } + +    /// Writes a platform-specific encoding of this socket address to +    /// the memory pointed to by `storage`, and returns the number of +    /// bytes used. +    /// +    /// # Safety +    /// +    /// `storage` must point to valid memory for encoding the socket +    /// address. +    pub unsafe fn write(&self, storage: *mut SocketAddrStorage) -> usize { +        backend::net::write_sockaddr::write_sockaddr(self, storage) +    } + +    /// Reads a platform-specific encoding of a socket address from +    /// the memory pointed to by `storage`, which uses `len` bytes. +    /// +    /// # Safety +    /// +    /// `storage` must point to valid memory for decoding a socket +    /// address. +    pub unsafe fn read(storage: *const SocketAddrStorage, len: usize) -> io::Result<Self> { +        backend::net::read_sockaddr::read_sockaddr(storage, len) +    } +} + +#[cfg(feature = "std")] +impl fmt::Debug for SocketAddrAny { +    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { +        match self { +            Self::V4(v4) => v4.fmt(fmt), +            Self::V6(v6) => v6.fmt(fmt), +            #[cfg(unix)] +            Self::Unix(unix) => unix.fmt(fmt), +        } +    } +} diff --git a/vendor/rustix/src/net/socketpair.rs b/vendor/rustix/src/net/socketpair.rs new file mode 100644 index 0000000..7228e71 --- /dev/null +++ b/vendor/rustix/src/net/socketpair.rs @@ -0,0 +1,36 @@ +use crate::fd::OwnedFd; +use crate::net::{AddressFamily, Protocol, SocketFlags, SocketType}; +use crate::{backend, io}; + +/// `socketpair(domain, type_ | accept_flags, protocol)`—Create a pair of +/// sockets that are connected to each other. +/// +/// # References +///  - [POSIX] +///  - [Linux] +///  - [Apple] +///  - [FreeBSD] +///  - [NetBSD] +///  - [OpenBSD] +///  - [DragonFly BSD] +///  - [illumos] +///  - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html +/// [Linux]: https://man7.org/linux/man-pages/man2/socketpair.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/socketpair.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=socketpair&sektion=2 +/// [NetBSD]: https://man.netbsd.org/socketpair.2 +/// [OpenBSD]: https://man.openbsd.org/socketpair.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=socketpair§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/socketpair +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Socket-Pairs.html +#[inline] +pub fn socketpair( +    domain: AddressFamily, +    type_: SocketType, +    flags: SocketFlags, +    protocol: Option<Protocol>, +) -> io::Result<(OwnedFd, OwnedFd)> { +    backend::net::syscalls::socketpair(domain, type_, flags, protocol) +} diff --git a/vendor/rustix/src/net/sockopt.rs b/vendor/rustix/src/net/sockopt.rs new file mode 100644 index 0000000..df04c4a --- /dev/null +++ b/vendor/rustix/src/net/sockopt.rs @@ -0,0 +1,1382 @@ +//! `getsockopt` and `setsockopt` functions. +//! +//! 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`] +//!  - [Winsock `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 +//! [Winsock `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`] +//!  - [Winsock `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 +//! [Winsock `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`] +//!  - [Winsock `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 +//! [Winsock `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`] +//!  - [Winsock `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 +//! [Winsock `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`] +//!  - [Winsock `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 +//! [Winsock `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`] +//!  - [Winsock `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 +//! [Winsock `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")] + +#[cfg(not(any( +    apple, +    windows, +    target_os = "aix", +    target_os = "dragonfly", +    target_os = "emscripten", +    target_os = "espidf", +    target_os = "haiku", +    target_os = "netbsd", +    target_os = "nto", +    target_os = "vita", +)))] +use crate::net::AddressFamily; +#[cfg(any( +    linux_kernel, +    target_os = "freebsd", +    target_os = "fuchsia", +    target_os = "openbsd", +    target_os = "redox", +    target_env = "newlib" +))] +use crate::net::Protocol; +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +use crate::net::SocketAddrV4; +#[cfg(linux_kernel)] +use crate::net::SocketAddrV6; +use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; +use crate::{backend, io}; +#[cfg(feature = "alloc")] +#[cfg(any( +    linux_like, +    target_os = "freebsd", +    target_os = "fuchsia", +    target_os = "illumos" +))] +use alloc::string::String; +use backend::c; +use backend::fd::AsFd; +use core::time::Duration; + +/// Timeout identifier for use with [`set_socket_timeout`] and +/// [`get_socket_timeout`]. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum Timeout { +    /// `SO_RCVTIMEO`—Timeout for receiving. +    Recv = c::SO_RCVTIMEO as _, + +    /// `SO_SNDTIMEO`—Timeout for sending. +    Send = c::SO_SNDTIMEO as _, +} + +/// `getsockopt(fd, SOL_SOCKET, SO_TYPE)`—Returns the type of a socket. +/// +/// 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: AsFd>(fd: Fd) -> io::Result<SocketType> { +    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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_reuseaddr(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_REUSEADDR)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_socket_reuseaddr(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_BROADCAST, value)` +/// +/// 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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_broadcast(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_BROADCAST)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(fd: Fd, value: Option<Duration>) -> io::Result<()> { +    backend::net::sockopt::set_socket_linger(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_LINGER)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<Option<Duration>> { +    backend::net::sockopt::get_socket_linger(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_PASSCRED, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_passcred(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_PASSCRED)` +/// +/// See the [module-level documentation] for more. +/// +/// [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: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_socket_passcred(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, id, value)`—Set the sending or receiving +/// timeout. +/// +/// 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 set_socket_timeout<Fd: AsFd>( +    fd: Fd, +    id: Timeout, +    value: Option<Duration>, +) -> io::Result<()> { +    backend::net::sockopt::set_socket_timeout(fd.as_fd(), id, value) +} + +/// `getsockopt(fd, SOL_SOCKET, id)`—Get the sending or receiving timeout. +/// +/// 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: AsFd>(fd: Fd, id: Timeout) -> io::Result<Option<Duration>> { +    backend::net::sockopt::get_socket_timeout(fd.as_fd(), id) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_ERROR)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<Result<(), io::Errno>> { +    backend::net::sockopt::get_socket_error(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(any(apple, freebsdlike, target_os = "netbsd"))] +#[doc(alias = "SO_NOSIGPIPE")] +#[inline] +pub fn get_socket_nosigpipe<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    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, freebsdlike, target_os = "netbsd"))] +#[doc(alias = "SO_NOSIGPIPE")] +#[inline] +pub fn set_socket_nosigpipe<Fd: AsFd>(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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_keepalive(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(fd: Fd, value: usize) -> io::Result<()> { +    backend::net::sockopt::set_socket_recv_buffer_size(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_RCVBUF)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<usize> { +    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: AsFd>(fd: Fd, value: usize) -> io::Result<()> { +    backend::net::sockopt::set_socket_send_buffer_size(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_SNDBUF)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<usize> { +    backend::net::sockopt::get_socket_send_buffer_size(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_DOMAIN)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(not(any( +    apple, +    windows, +    target_os = "aix", +    target_os = "dragonfly", +    target_os = "emscripten", +    target_os = "espidf", +    target_os = "haiku", +    target_os = "netbsd", +    target_os = "nto", +    target_os = "vita", +)))] +#[inline] +#[doc(alias = "SO_DOMAIN")] +pub fn get_socket_domain<Fd: AsFd>(fd: Fd) -> io::Result<AddressFamily> { +    backend::net::sockopt::get_socket_domain(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(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: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_socket_oobinline(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(not(any(solarish, windows)))] +#[cfg(not(windows))] +#[inline] +#[doc(alias = "SO_REUSEPORT")] +pub fn set_socket_reuseport<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_reuseport(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_REUSEPORT)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(not(any(solarish, windows)))] +#[inline] +#[doc(alias = "SO_REUSEPORT")] +pub fn get_socket_reuseport<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_socket_reuseport(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_REUSEPORT_LB, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(target_os = "freebsd")] +#[inline] +#[doc(alias = "SO_REUSEPORT_LB")] +pub fn set_socket_reuseport_lb<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_socket_reuseport_lb(fd.as_fd(), value) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_REUSEPORT_LB)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(target_os = "freebsd")] +#[inline] +#[doc(alias = "SO_REUSEPORT_LB")] +pub fn get_socket_reuseport_lb<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_socket_reuseport_lb(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_PROTOCOL)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(any( +    linux_kernel, +    target_os = "freebsd", +    target_os = "fuchsia", +    target_os = "openbsd", +    target_os = "redox", +    target_env = "newlib" +))] +#[inline] +#[doc(alias = "SO_PROTOCOL")] +pub fn get_socket_protocol<Fd: AsFd>(fd: Fd) -> io::Result<Option<Protocol>> { +    backend::net::sockopt::get_socket_protocol(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_COOKIE)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(target_os = "linux")] +#[inline] +#[doc(alias = "SO_COOKIE")] +pub fn get_socket_cookie<Fd: AsFd>(fd: Fd) -> io::Result<u64> { +    backend::net::sockopt::get_socket_cookie(fd.as_fd()) +} + +/// `getsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(target_os = "linux")] +#[inline] +#[doc(alias = "SO_INCOMING_CPU")] +pub fn get_socket_incoming_cpu<Fd: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_socket_incoming_cpu(fd.as_fd()) +} + +/// `setsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions +#[cfg(target_os = "linux")] +#[inline] +#[doc(alias = "SO_INCOMING_CPU")] +pub fn set_socket_incoming_cpu<Fd: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_socket_incoming_cpu(fd.as_fd(), value) +} + +/// `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: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_ip_ttl(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_TTL)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_ip_ttl(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, value)` +/// +/// 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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_v6only(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_ip_multicast_loop(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_ip_multicast_ttl(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<u32> { +    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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_multicast_loop(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_ipv6_multicast_loop(fd.as_fd()) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<u8> { +    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: AsFd>(fd: Fd, value: Option<u8>) -> 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: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_multicast_hops(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS)` +/// +/// 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 get_ipv6_multicast_hops<Fd: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_ipv6_multicast_hops(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, multiaddr, interface)` +/// +/// 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<Fd: AsFd>( +    fd: Fd, +    multiaddr: &Ipv4Addr, +    interface: &Ipv4Addr, +) -> io::Result<()> { +    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: AsFd>( +    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, value)` +/// +/// 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: AsFd>( +    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, value)` +/// +/// 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: AsFd>( +    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)` +/// +/// 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")] +pub fn set_ipv6_add_membership<Fd: AsFd>( +    fd: Fd, +    multiaddr: &Ipv6Addr, +    interface: u32, +) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_add_membership(fd.as_fd(), multiaddr, interface) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, multiaddr, interface)` +/// +/// 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<Fd: AsFd>( +    fd: Fd, +    multiaddr: &Ipv4Addr, +    interface: &Ipv4Addr, +) -> io::Result<()> { +    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: AsFd>( +    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)` +/// +/// 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")] +pub fn set_ipv6_drop_membership<Fd: AsFd>( +    fd: Fd, +    multiaddr: &Ipv6Addr, +    interface: u32, +) -> io::Result<()> { +    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: AsFd>(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: AsFd>(fd: Fd) -> io::Result<u8> { +    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: AsFd>(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: AsFd>(fd: Fd) -> io::Result<bool> { +    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: AsFd>(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: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_ipv6_recvtclass(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IP, IP_FREEBIND, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "IP_FREEBIND")] +pub fn set_ip_freebind<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_ip_freebind(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IP, IP_FREEBIND)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "IP_FREEBIND")] +pub fn get_ip_freebind<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_ip_freebind(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_FREEBIND, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "IPV6_FREEBIND")] +pub fn set_ipv6_freebind<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_freebind(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_FREEBIND)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "IPV6_FREEBIND")] +pub fn get_ipv6_freebind<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_ipv6_freebind(fd.as_fd()) +} + +/// `getsockopt(fd, IPPROTO_IP, SO_ORIGINAL_DST)` +/// +/// Even though this corresponnds to a `SO_*` constant, it is an `IPPROTO_IP` +/// option. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "SO_ORIGINAL_DST")] +pub fn get_ip_original_dst<Fd: AsFd>(fd: Fd) -> io::Result<SocketAddrV4> { +    backend::net::sockopt::get_ip_original_dst(fd.as_fd()) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST)` +/// +/// Even though this corresponnds to a `IP6T_*` constant, it is an +/// `IPPROTO_IPV6` option. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "IP6T_SO_ORIGINAL_DST")] +pub fn get_ipv6_original_dst<Fd: AsFd>(fd: Fd) -> io::Result<SocketAddrV6> { +    backend::net::sockopt::get_ipv6_original_dst(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(not(any( +    solarish, +    windows, +    target_os = "espidf", +    target_os = "haiku", +    target_os = "vita" +)))] +#[inline] +#[doc(alias = "IPV6_TCLASS")] +pub fn set_ipv6_tclass<Fd: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_ipv6_tclass(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions +#[cfg(not(any( +    solarish, +    windows, +    target_os = "espidf", +    target_os = "haiku", +    target_os = "vita" +)))] +#[inline] +#[doc(alias = "IPV6_TCLASS")] +pub fn get_ipv6_tclass<Fd: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_ipv6_tclass(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: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_tcp_nodelay(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_NODELAY)` +/// +/// 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: AsFd>(fd: Fd) -> io::Result<bool> { +    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 +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPCNT")] +pub fn set_tcp_keepcnt<Fd: AsFd>(fd: Fd, value: u32) -> io::Result<()> { +    backend::net::sockopt::set_tcp_keepcnt(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPCNT")] +pub fn get_tcp_keepcnt<Fd: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_tcp_keepcnt(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, value)` +/// +/// `TCP_KEEPALIVE` on Apple platforms. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPIDLE")] +pub fn set_tcp_keepidle<Fd: AsFd>(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. +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPIDLE")] +pub fn get_tcp_keepidle<Fd: AsFd>(fd: Fd) -> io::Result<Duration> { +    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 +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPINTVL")] +pub fn set_tcp_keepintvl<Fd: AsFd>(fd: Fd, value: Duration) -> io::Result<()> { +    backend::net::sockopt::set_tcp_keepintvl(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "nto")))] +#[inline] +#[doc(alias = "TCP_KEEPINTVL")] +pub fn get_tcp_keepintvl<Fd: AsFd>(fd: Fd) -> io::Result<Duration> { +    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 +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_USER_TIMEOUT")] +pub fn set_tcp_user_timeout<Fd: AsFd>(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 +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_USER_TIMEOUT")] +pub fn get_tcp_user_timeout<Fd: AsFd>(fd: Fd) -> io::Result<u32> { +    backend::net::sockopt::get_tcp_user_timeout(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_QUICKACK")] +pub fn set_tcp_quickack<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_tcp_quickack(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_QUICKACK)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_QUICKACK")] +pub fn get_tcp_quickack<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_tcp_quickack(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any( +    linux_like, +    target_os = "freebsd", +    target_os = "fuchsia", +    target_os = "illumos" +))] +#[inline] +#[doc(alias = "TCP_CONGESTION")] +pub fn set_tcp_congestion<Fd: AsFd>(fd: Fd, value: &str) -> io::Result<()> { +    backend::net::sockopt::set_tcp_congestion(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_CONGESTION)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(feature = "alloc")] +#[cfg(any( +    linux_like, +    target_os = "freebsd", +    target_os = "fuchsia", +    target_os = "illumos" +))] +#[inline] +#[doc(alias = "TCP_CONGESTION")] +pub fn get_tcp_congestion<Fd: AsFd>(fd: Fd) -> io::Result<String> { +    backend::net::sockopt::get_tcp_congestion(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_THIN_LINEAR_TIMEOUTS")] +pub fn set_tcp_thin_linear_timeouts<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_tcp_thin_linear_timeouts(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_THIN_LINEAR_TIMEOUTS")] +pub fn get_tcp_thin_linear_timeouts<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_tcp_thin_linear_timeouts(fd.as_fd()) +} + +/// `setsockopt(fd, IPPROTO_TCP, TCP_CORK, value)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, solarish, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_CORK")] +pub fn set_tcp_cork<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { +    backend::net::sockopt::set_tcp_cork(fd.as_fd(), value) +} + +/// `getsockopt(fd, IPPROTO_TCP, TCP_CORK)` +/// +/// See the [module-level documentation] for more. +/// +/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions +#[cfg(any(linux_like, solarish, target_os = "fuchsia"))] +#[inline] +#[doc(alias = "TCP_CORK")] +pub fn get_tcp_cork<Fd: AsFd>(fd: Fd) -> io::Result<bool> { +    backend::net::sockopt::get_tcp_cork(fd.as_fd()) +} + +/// Get credentials of Unix domain socket peer process +/// +/// # References +///  - [Linux `unix`] +/// +/// [Linux `unix`]: https://man7.org/linux/man-pages/man7/unix.7.html +#[cfg(linux_kernel)] +#[doc(alias = "SO_PEERCRED")] +pub fn get_socket_peercred<Fd: AsFd>(fd: Fd) -> io::Result<super::UCred> { +    backend::net::sockopt::get_socket_peercred(fd.as_fd()) +} + +#[test] +fn test_sizes() { +    use c::c_int; + +    // Backend code needs to cast these to `c_int` so make sure that cast +    // isn't lossy. +    assert_eq_size!(Timeout, c_int); +} diff --git a/vendor/rustix/src/net/types.rs b/vendor/rustix/src/net/types.rs new file mode 100644 index 0000000..ad60e36 --- /dev/null +++ b/vendor/rustix/src/net/types.rs @@ -0,0 +1,1495 @@ +//! Types and constants for `rustix::net`. + +use crate::backend::c; +use bitflags::bitflags; + +/// A type for holding raw integer socket types. +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 as _); + +    /// `SOCK_DGRAM` +    pub const DGRAM: Self = Self(c::SOCK_DGRAM as _); + +    /// `SOCK_SEQPACKET` +    #[cfg(not(target_os = "espidf"))] +    pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET as _); + +    /// `SOCK_RAW` +    #[cfg(not(target_os = "espidf"))] +    pub const RAW: Self = Self(c::SOCK_RAW as _); + +    /// `SOCK_RDM` +    #[cfg(not(any(target_os = "espidf", target_os = "haiku")))] +    pub const RDM: Self = Self(c::SOCK_RDM as _); + +    /// 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. +pub type RawAddressFamily = c::sa_family_t; + +/// `AF_*` constants for use with [`socket`], [`socket_with`], and +/// [`socketpair`]. +/// +/// [`socket`]: crate::net::socket() +/// [`socket_with`]: crate::net::socket_with +/// [`socketpair`]: crate::net::socketpair() +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(transparent)] +pub struct AddressFamily(pub(crate) RawAddressFamily); + +#[rustfmt::skip] +#[allow(non_upper_case_globals)] +impl AddressFamily { +    /// `AF_UNSPEC` +    pub const UNSPEC: Self = Self(c::AF_UNSPEC as _); +    /// `AF_INET` +    /// +    /// # References +    ///  - [Linux] +    /// +    /// [Linux]: https://man7.org/linux/man-pages/man7/ip.7.html +    pub const INET: Self = Self(c::AF_INET as _); +    /// `AF_INET6` +    /// +    /// # References +    ///  - [Linux] +    /// +    /// [Linux]: https://man7.org/linux/man-pages/man7/ipv6.7.html +    pub const INET6: Self = Self(c::AF_INET6 as _); +    /// `AF_NETLINK` +    /// +    /// # References +    ///  - [Linux] +    /// +    /// [Linux]: https://man7.org/linux/man-pages/man7/netlink.7.html +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    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` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const AX25: Self = Self(c::AF_AX25 as _); +    /// `AF_IPX` +    #[cfg(not(any( +        target_os = "aix", +        target_os = "espidf", +        target_os = "vita", +    )))] +    pub const IPX: Self = Self(c::AF_IPX as _); +    /// `AF_APPLETALK` +    #[cfg(not(any(target_os = "espidf", target_os = "vita")))] +    pub const APPLETALK: Self = Self(c::AF_APPLETALK as _); +    /// `AF_NETROM` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const NETROM: Self = Self(c::AF_NETROM as _); +    /// `AF_BRIDGE` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const BRIDGE: Self = Self(c::AF_BRIDGE as _); +    /// `AF_ATMPVC` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const ATMPVC: Self = Self(c::AF_ATMPVC as _); +    /// `AF_X25` +    #[cfg(not(any( +        bsd, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const X25: Self = Self(c::AF_X25 as _); +    /// `AF_ROSE` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const ROSE: Self = Self(c::AF_ROSE as _); +    /// `AF_DECnet` +    #[cfg(not(any(target_os = "espidf", target_os = "haiku", target_os = "vita")))] +    pub const DECnet: Self = Self(c::AF_DECnet as _); +    /// `AF_NETBEUI` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const NETBEUI: Self = Self(c::AF_NETBEUI as _); +    /// `AF_SECURITY` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const SECURITY: Self = Self(c::AF_SECURITY as _); +    /// `AF_KEY` +    #[cfg(not(any( +        bsd, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const KEY: Self = Self(c::AF_KEY as _); +    /// `AF_PACKET` +    /// +    /// # References +    ///  - [Linux] +    /// +    /// [Linux]: https://man7.org/linux/man-pages/man7/packet.7.html +    #[cfg(not(any( +        bsd, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const PACKET: Self = Self(c::AF_PACKET as _); +    /// `AF_ASH` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const ASH: Self = Self(c::AF_ASH as _); +    /// `AF_ECONET` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const ECONET: Self = Self(c::AF_ECONET as _); +    /// `AF_ATMSVC` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const ATMSVC: Self = Self(c::AF_ATMSVC as _); +    /// `AF_RDS` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const RDS: Self = Self(c::AF_RDS as _); +    /// `AF_SNA` +    #[cfg(not(any(target_os = "espidf", target_os = "haiku", target_os = "vita")))] +    pub const SNA: Self = Self(c::AF_SNA as _); +    /// `AF_IRDA` +    #[cfg(not(any( +        bsd, +        solarish, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const IRDA: Self = Self(c::AF_IRDA as _); +    /// `AF_PPPOX` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const PPPOX: Self = Self(c::AF_PPPOX as _); +    /// `AF_WANPIPE` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const WANPIPE: Self = Self(c::AF_WANPIPE as _); +    /// `AF_LLC` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const LLC: Self = Self(c::AF_LLC as _); +    /// `AF_CAN` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const CAN: Self = Self(c::AF_CAN as _); +    /// `AF_TIPC` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const TIPC: Self = Self(c::AF_TIPC as _); +    /// `AF_BLUETOOTH` +    #[cfg(not(any( +        apple, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "vita", +    )))] +    pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _); +    /// `AF_IUCV` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const IUCV: Self = Self(c::AF_IUCV as _); +    /// `AF_RXRPC` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const RXRPC: Self = Self(c::AF_RXRPC as _); +    /// `AF_ISDN` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita", +    )))] +    pub const ISDN: Self = Self(c::AF_ISDN as _); +    /// `AF_PHONET` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const PHONET: Self = Self(c::AF_PHONET as _); +    /// `AF_IEEE802154` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _); +    /// `AF_802` +    #[cfg(solarish)] +    pub const EIGHT_ZERO_TWO: Self = Self(c::AF_802 as _); +    #[cfg(target_os = "fuchsia")] +    /// `AF_ALG` +    pub const ALG: Self = Self(c::AF_ALG as _); +    #[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "nto"))] +    /// `AF_ARP` +    pub const ARP: Self = Self(c::AF_ARP as _); +    /// `AF_ATM` +    #[cfg(freebsdlike)] +    pub const ATM: Self = Self(c::AF_ATM as _); +    /// `AF_CAIF` +    #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia"))] +    pub const CAIF: Self = Self(c::AF_CAIF as _); +    /// `AF_CCITT` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const CCITT: Self = Self(c::AF_CCITT as _); +    /// `AF_CHAOS` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const CHAOS: Self = Self(c::AF_CHAOS as _); +    /// `AF_CNT` +    #[cfg(any(bsd, target_os = "nto"))] +    pub const CNT: Self = Self(c::AF_CNT as _); +    /// `AF_COIP` +    #[cfg(any(bsd, target_os = "nto"))] +    pub const COIP: Self = Self(c::AF_COIP as _); +    /// `AF_DATAKIT` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const DATAKIT: Self = Self(c::AF_DATAKIT as _); +    /// `AF_DLI` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))] +    pub const DLI: Self = Self(c::AF_DLI as _); +    /// `AF_E164` +    #[cfg(any(bsd, target_os = "nto"))] +    pub const E164: Self = Self(c::AF_E164 as _); +    /// `AF_ECMA` +    #[cfg(any(apple, freebsdlike, solarish, target_os = "aix", target_os = "nto", target_os = "openbsd"))] +    pub const ECMA: Self = Self(c::AF_ECMA as _); +    /// `AF_ENCAP` +    #[cfg(target_os = "openbsd")] +    pub const ENCAP: Self = Self(c::AF_ENCAP as _); +    /// `AF_FILE` +    #[cfg(solarish)] +    pub const FILE: Self = Self(c::AF_FILE as _); +    /// `AF_GOSIP` +    #[cfg(solarish)] +    pub const GOSIP: Self = Self(c::AF_GOSIP as _); +    /// `AF_HYLINK` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const HYLINK: Self = Self(c::AF_HYLINK as _); +    /// `AF_IB` +    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] +    pub const IB: Self = Self(c::AF_IB as _); +    /// `AF_IMPLINK` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const IMPLINK: Self = Self(c::AF_IMPLINK as _); +    /// `AF_IEEE80211` +    #[cfg(any(apple, freebsdlike, target_os = "netbsd"))] +    pub const IEEE80211: Self = Self(c::AF_IEEE80211 as _); +    /// `AF_INET6_SDP` +    #[cfg(target_os = "freebsd")] +    pub const INET6_SDP: Self = Self(c::AF_INET6_SDP as _); +    /// `AF_INET_OFFLOAD` +    #[cfg(solarish)] +    pub const INET_OFFLOAD: Self = Self(c::AF_INET_OFFLOAD as _); +    /// `AF_INET_SDP` +    #[cfg(target_os = "freebsd")] +    pub const INET_SDP: Self = Self(c::AF_INET_SDP as _); +    /// `AF_INTF` +    #[cfg(target_os = "aix")] +    pub const INTF: Self = Self(c::AF_INTF as _); +    /// `AF_ISO` +    #[cfg(any(bsd, target_os = "aix", target_os = "nto"))] +    pub const ISO: Self = Self(c::AF_ISO as _); +    /// `AF_LAT` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const LAT: Self = Self(c::AF_LAT as _); +    /// `AF_LINK` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))] +    pub const LINK: Self = Self(c::AF_LINK as _); +    /// `AF_MPLS` +    #[cfg(any(netbsdlike, target_os = "dragonfly", target_os = "emscripten", target_os = "fuchsia"))] +    pub const MPLS: Self = Self(c::AF_MPLS as _); +    /// `AF_NATM` +    #[cfg(any(bsd, target_os = "nto"))] +    pub const NATM: Self = Self(c::AF_NATM as _); +    /// `AF_NBS` +    #[cfg(solarish)] +    pub const NBS: Self = Self(c::AF_NBS as _); +    /// `AF_NCA` +    #[cfg(solarish)] +    pub const NCA: Self = Self(c::AF_NCA as _); +    /// `AF_NDD` +    #[cfg(target_os = "aix")] +    pub const NDD: Self = Self(c::AF_NDD as _); +    /// `AF_NDRV` +    #[cfg(apple)] +    pub const NDRV: Self = Self(c::AF_NDRV as _); +    /// `AF_NETBIOS` +    #[cfg(any(apple, freebsdlike))] +    pub const NETBIOS: Self = Self(c::AF_NETBIOS as _); +    /// `AF_NETGRAPH` +    #[cfg(freebsdlike)] +    pub const NETGRAPH: Self = Self(c::AF_NETGRAPH as _); +    /// `AF_NIT` +    #[cfg(solarish)] +    pub const NIT: Self = Self(c::AF_NIT as _); +    /// `AF_NOTIFY` +    #[cfg(target_os = "haiku")] +    pub const NOTIFY: Self = Self(c::AF_NOTIFY as _); +    /// `AF_NFC` +    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] +    pub const NFC: Self = Self(c::AF_NFC as _); +    /// `AF_NS` +    #[cfg(any(apple, solarish, netbsdlike, target_os = "aix", target_os = "nto"))] +    pub const NS: Self = Self(c::AF_NS as _); +    /// `AF_OROUTE` +    #[cfg(target_os = "netbsd")] +    pub const OROUTE: Self = Self(c::AF_OROUTE as _); +    /// `AF_OSI` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const OSI: Self = Self(c::AF_OSI as _); +    /// `AF_OSINET` +    #[cfg(solarish)] +    pub const OSINET: Self = Self(c::AF_OSINET as _); +    /// `AF_POLICY` +    #[cfg(solarish)] +    pub const POLICY: Self = Self(c::AF_POLICY as _); +    /// `AF_PPP` +    #[cfg(apple)] +    pub const PPP: Self = Self(c::AF_PPP as _); +    /// `AF_PUP` +    #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] +    pub const PUP: Self = Self(c::AF_PUP as _); +    /// `AF_RIF` +    #[cfg(target_os = "aix")] +    pub const RIF: Self = Self(c::AF_RIF as _); +    /// `AF_ROUTE` +    #[cfg(any(bsd, solarish, target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "haiku", target_os = "nto"))] +    pub const ROUTE: Self = Self(c::AF_ROUTE as _); +    /// `AF_SCLUSTER` +    #[cfg(target_os = "freebsd")] +    pub const SCLUSTER: Self = Self(c::AF_SCLUSTER as _); +    /// `AF_SIP` +    #[cfg(any(apple, target_os = "freebsd", target_os = "openbsd"))] +    pub const SIP: Self = Self(c::AF_SIP as _); +    /// `AF_SLOW` +    #[cfg(target_os = "freebsd")] +    pub const SLOW: Self = Self(c::AF_SLOW as _); +    /// `AF_SYS_CONTROL` +    #[cfg(apple)] +    pub const SYS_CONTROL: Self = Self(c::AF_SYS_CONTROL as _); +    /// `AF_SYSTEM` +    #[cfg(apple)] +    pub const SYSTEM: Self = Self(c::AF_SYSTEM as _); +    /// `AF_TRILL` +    #[cfg(solarish)] +    pub const TRILL: Self = Self(c::AF_TRILL as _); +    /// `AF_UTUN` +    #[cfg(apple)] +    pub const UTUN: Self = Self(c::AF_UTUN as _); +    /// `AF_VSOCK` +    #[cfg(any(apple, target_os = "emscripten", target_os = "fuchsia"))] +    pub const VSOCK: Self = Self(c::AF_VSOCK 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. +pub type RawProtocol = core::num::NonZeroU32; + +const fn new_raw_protocol(u: u32) -> RawProtocol { +    match RawProtocol::new(u) { +        Some(p) => p, +        None => panic!("new_raw_protocol: protocol must be non-zero"), +    } +} + +/// `IPPROTO_*` and other constants for use with [`socket`], [`socket_with`], +/// and [`socketpair`] when a nondefault value is desired. See the [`ipproto`], +/// [`sysproto`], and [`netlink`] modules for possible values. +/// +/// For the default values, such as `IPPROTO_IP` or `NETLINK_ROUTE`, pass +/// `None` as the `protocol` argument in these functions. +/// +/// [`socket`]: crate::net::socket() +/// [`socket_with`]: crate::net::socket_with +/// [`socketpair`]: crate::net::socketpair() +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(transparent)] +#[doc(alias = "IPPROTO_IP")] +#[doc(alias = "NETLINK_ROUTE")] +pub struct Protocol(pub(crate) RawProtocol); + +/// `IPPROTO_*` constants. +/// +/// For `IPPROTO_IP`, pass `None` as the `protocol` argument. +pub mod ipproto { +    use super::{new_raw_protocol, Protocol}; +    use crate::backend::c; + +    /// `IPPROTO_ICMP` +    pub const ICMP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ICMP as _)); +    /// `IPPROTO_IGMP` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const IGMP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_IGMP as _)); +    /// `IPPROTO_IPIP` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const IPIP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_IPIP as _)); +    /// `IPPROTO_TCP` +    pub const TCP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_TCP as _)); +    /// `IPPROTO_EGP` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const EGP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_EGP as _)); +    /// `IPPROTO_PUP` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const PUP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_PUP as _)); +    /// `IPPROTO_UDP` +    pub const UDP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_UDP as _)); +    /// `IPPROTO_IDP` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const IDP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_IDP as _)); +    /// `IPPROTO_TP` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const TP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_TP as _)); +    /// `IPPROTO_DCCP` +    #[cfg(not(any( +        apple, +        solarish, +        windows, +        target_os = "aix", +        target_os = "dragonfly", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "openbsd", +        target_os = "vita", +    )))] +    pub const DCCP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_DCCP as _)); +    /// `IPPROTO_IPV6` +    pub const IPV6: Protocol = Protocol(new_raw_protocol(c::IPPROTO_IPV6 as _)); +    /// `IPPROTO_RSVP` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const RSVP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_RSVP as _)); +    /// `IPPROTO_GRE` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const GRE: Protocol = Protocol(new_raw_protocol(c::IPPROTO_GRE as _)); +    /// `IPPROTO_ESP` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const ESP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ESP as _)); +    /// `IPPROTO_AH` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const AH: Protocol = Protocol(new_raw_protocol(c::IPPROTO_AH as _)); +    /// `IPPROTO_MTP` +    #[cfg(not(any( +        solarish, +        netbsdlike, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const MTP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_MTP as _)); +    /// `IPPROTO_BEETPH` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const BEETPH: Protocol = Protocol(new_raw_protocol(c::IPPROTO_BEETPH as _)); +    /// `IPPROTO_ENCAP` +    #[cfg(not(any( +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita", +    )))] +    pub const ENCAP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ENCAP as _)); +    /// `IPPROTO_PIM` +    #[cfg(not(any( +        solarish, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const PIM: Protocol = Protocol(new_raw_protocol(c::IPPROTO_PIM as _)); +    /// `IPPROTO_COMP` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const COMP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_COMP as _)); +    /// `IPPROTO_SCTP` +    #[cfg(not(any( +        solarish, +        target_os = "dragonfly", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "openbsd", +        target_os = "vita", +    )))] +    pub const SCTP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_SCTP as _)); +    /// `IPPROTO_UDPLITE` +    #[cfg(not(any( +        apple, +        netbsdlike, +        solarish, +        windows, +        target_os = "aix", +        target_os = "dragonfly", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const UDPLITE: Protocol = Protocol(new_raw_protocol(c::IPPROTO_UDPLITE as _)); +    /// `IPPROTO_MPLS` +    #[cfg(not(any( +        apple, +        solarish, +        windows, +        target_os = "aix", +        target_os = "dragonfly", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "netbsd", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const MPLS: Protocol = Protocol(new_raw_protocol(c::IPPROTO_MPLS as _)); +    /// `IPPROTO_ETHERNET` +    #[cfg(linux_kernel)] +    pub const ETHERNET: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ETHERNET as _)); +    /// `IPPROTO_RAW` +    #[cfg(not(any(target_os = "espidf", target_os = "vita")))] +    pub const RAW: Protocol = Protocol(new_raw_protocol(c::IPPROTO_RAW as _)); +    /// `IPPROTO_MPTCP` +    #[cfg(not(any( +        bsd, +        solarish, +        windows, +        target_os = "aix", +        target_os = "emscripten", +        target_os = "espidf", +        target_os = "fuchsia", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const MPTCP: Protocol = Protocol(new_raw_protocol(c::IPPROTO_MPTCP as _)); +    /// `IPPROTO_FRAGMENT` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const FRAGMENT: Protocol = Protocol(new_raw_protocol(c::IPPROTO_FRAGMENT as _)); +    /// `IPPROTO_ICMPV6` +    pub const ICMPV6: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ICMPV6 as _)); +    /// `IPPROTO_MH` +    #[cfg(not(any( +        apple, +        netbsdlike, +        solarish, +        windows, +        target_os = "dragonfly", +        target_os = "espidf", +        target_os = "haiku", +        target_os = "nto", +        target_os = "vita", +    )))] +    pub const MH: Protocol = Protocol(new_raw_protocol(c::IPPROTO_MH as _)); +    /// `IPPROTO_ROUTING` +    #[cfg(not(any( +        solarish, +        target_os = "espidf", +        target_os = "haiku", +        target_os = "vita" +    )))] +    pub const ROUTING: Protocol = Protocol(new_raw_protocol(c::IPPROTO_ROUTING as _)); +} + +/// `SYSPROTO_*` constants. +pub mod sysproto { +    #[cfg(apple)] +    use { +        super::{new_raw_protocol, Protocol}, +        crate::backend::c, +    }; + +    /// `SYSPROTO_EVENT` +    #[cfg(apple)] +    pub const EVENT: Protocol = Protocol(new_raw_protocol(c::SYSPROTO_EVENT as _)); + +    /// `SYSPROTO_CONTROL` +    #[cfg(apple)] +    pub const CONTROL: Protocol = Protocol(new_raw_protocol(c::SYSPROTO_CONTROL as _)); +} + +/// `NETLINK_*` constants. +/// +/// For `NETLINK_ROUTE`, pass `None` as the `protocol` argument. +pub mod netlink { +    #[cfg(linux_kernel)] +    use { +        super::{new_raw_protocol, Protocol}, +        crate::backend::c, +    }; + +    /// `NETLINK_UNUSED` +    #[cfg(linux_kernel)] +    pub const UNUSED: Protocol = Protocol(new_raw_protocol(c::NETLINK_UNUSED as _)); +    /// `NETLINK_USERSOCK` +    #[cfg(linux_kernel)] +    pub const USERSOCK: Protocol = Protocol(new_raw_protocol(c::NETLINK_USERSOCK as _)); +    /// `NETLINK_FIREWALL` +    #[cfg(linux_kernel)] +    pub const FIREWALL: Protocol = Protocol(new_raw_protocol(c::NETLINK_FIREWALL as _)); +    /// `NETLINK_SOCK_DIAG` +    #[cfg(linux_kernel)] +    pub const SOCK_DIAG: Protocol = Protocol(new_raw_protocol(c::NETLINK_SOCK_DIAG as _)); +    /// `NETLINK_NFLOG` +    #[cfg(linux_kernel)] +    pub const NFLOG: Protocol = Protocol(new_raw_protocol(c::NETLINK_NFLOG as _)); +    /// `NETLINK_XFRM` +    #[cfg(linux_kernel)] +    pub const XFRM: Protocol = Protocol(new_raw_protocol(c::NETLINK_XFRM as _)); +    /// `NETLINK_SELINUX` +    #[cfg(linux_kernel)] +    pub const SELINUX: Protocol = Protocol(new_raw_protocol(c::NETLINK_SELINUX as _)); +    /// `NETLINK_ISCSI` +    #[cfg(linux_kernel)] +    pub const ISCSI: Protocol = Protocol(new_raw_protocol(c::NETLINK_ISCSI as _)); +    /// `NETLINK_AUDIT` +    #[cfg(linux_kernel)] +    pub const AUDIT: Protocol = Protocol(new_raw_protocol(c::NETLINK_AUDIT as _)); +    /// `NETLINK_FIB_LOOKUP` +    #[cfg(linux_kernel)] +    pub const FIB_LOOKUP: Protocol = Protocol(new_raw_protocol(c::NETLINK_FIB_LOOKUP as _)); +    /// `NETLINK_CONNECTOR` +    #[cfg(linux_kernel)] +    pub const CONNECTOR: Protocol = Protocol(new_raw_protocol(c::NETLINK_CONNECTOR as _)); +    /// `NETLINK_NETFILTER` +    #[cfg(linux_kernel)] +    pub const NETFILTER: Protocol = Protocol(new_raw_protocol(c::NETLINK_NETFILTER as _)); +    /// `NETLINK_IP6_FW` +    #[cfg(linux_kernel)] +    pub const IP6_FW: Protocol = Protocol(new_raw_protocol(c::NETLINK_IP6_FW as _)); +    /// `NETLINK_DNRTMSG` +    #[cfg(linux_kernel)] +    pub const DNRTMSG: Protocol = Protocol(new_raw_protocol(c::NETLINK_DNRTMSG as _)); +    /// `NETLINK_KOBJECT_UEVENT` +    #[cfg(linux_kernel)] +    pub const KOBJECT_UEVENT: Protocol = Protocol(new_raw_protocol(c::NETLINK_KOBJECT_UEVENT as _)); +    /// `NETLINK_GENERIC` +    // This is defined on FreeBSD too, but it has the value 0, so it doesn't +    // fit in or `NonZeroU32`. It's unclear whether FreeBSD intends +    // `NETLINK_GENERIC` to be the default when Linux has `NETLINK_ROUTE` +    // as the default. +    #[cfg(linux_kernel)] +    pub const GENERIC: Protocol = Protocol(new_raw_protocol(c::NETLINK_GENERIC as _)); +    /// `NETLINK_SCSITRANSPORT` +    #[cfg(linux_kernel)] +    pub const SCSITRANSPORT: Protocol = Protocol(new_raw_protocol(c::NETLINK_SCSITRANSPORT as _)); +    /// `NETLINK_ECRYPTFS` +    #[cfg(linux_kernel)] +    pub const ECRYPTFS: Protocol = Protocol(new_raw_protocol(c::NETLINK_ECRYPTFS as _)); +    /// `NETLINK_RDMA` +    #[cfg(linux_kernel)] +    pub const RDMA: Protocol = Protocol(new_raw_protocol(c::NETLINK_RDMA as _)); +    /// `NETLINK_CRYPTO` +    #[cfg(linux_kernel)] +    pub const CRYPTO: Protocol = Protocol(new_raw_protocol(c::NETLINK_CRYPTO as _)); +    /// `NETLINK_INET_DIAG` +    #[cfg(linux_kernel)] +    pub const INET_DIAG: Protocol = Protocol(new_raw_protocol(c::NETLINK_INET_DIAG as _)); +    /// `NETLINK_ADD_MEMBERSHIP` +    #[cfg(linux_kernel)] +    pub const ADD_MEMBERSHIP: Protocol = Protocol(new_raw_protocol(c::NETLINK_ADD_MEMBERSHIP as _)); +    /// `NETLINK_DROP_MEMBERSHIP` +    #[cfg(linux_kernel)] +    pub const DROP_MEMBERSHIP: Protocol = +        Protocol(new_raw_protocol(c::NETLINK_DROP_MEMBERSHIP as _)); +    /// `NETLINK_PKTINFO` +    #[cfg(linux_kernel)] +    pub const PKTINFO: Protocol = Protocol(new_raw_protocol(c::NETLINK_PKTINFO as _)); +    /// `NETLINK_BROADCAST_ERROR` +    #[cfg(linux_kernel)] +    pub const BROADCAST_ERROR: Protocol = +        Protocol(new_raw_protocol(c::NETLINK_BROADCAST_ERROR as _)); +    /// `NETLINK_NO_ENOBUFS` +    #[cfg(linux_kernel)] +    pub const NO_ENOBUFS: Protocol = Protocol(new_raw_protocol(c::NETLINK_NO_ENOBUFS as _)); +    /// `NETLINK_RX_RING` +    #[cfg(linux_kernel)] +    pub const RX_RING: Protocol = Protocol(new_raw_protocol(c::NETLINK_RX_RING as _)); +    /// `NETLINK_TX_RING` +    #[cfg(linux_kernel)] +    pub const TX_RING: Protocol = Protocol(new_raw_protocol(c::NETLINK_TX_RING as _)); +    /// `NETLINK_LISTEN_ALL_NSID` +    #[cfg(linux_kernel)] +    pub const LISTEN_ALL_NSID: Protocol = +        Protocol(new_raw_protocol(c::NETLINK_LISTEN_ALL_NSID as _)); +    /// `NETLINK_LIST_MEMBERSHIPS` +    #[cfg(linux_kernel)] +    pub const LIST_MEMBERSHIPS: Protocol = +        Protocol(new_raw_protocol(c::NETLINK_LIST_MEMBERSHIPS as _)); +    /// `NETLINK_CAP_ACK` +    #[cfg(linux_kernel)] +    pub const CAP_ACK: Protocol = Protocol(new_raw_protocol(c::NETLINK_CAP_ACK as _)); +    /// `NETLINK_EXT_ACK` +    #[cfg(linux_kernel)] +    pub const EXT_ACK: Protocol = Protocol(new_raw_protocol(c::NETLINK_EXT_ACK as _)); +    /// `NETLINK_GET_STRICT_CHK` +    #[cfg(linux_kernel)] +    pub const GET_STRICT_CHK: Protocol = Protocol(new_raw_protocol(c::NETLINK_GET_STRICT_CHK as _)); +} + +/// `ETH_P_*` constants. +// These are translated into 16-bit big-endian form because that's what the +// [`AddressFamily::PACKET`] address family [expects]. +// +// [expects]: https://man7.org/linux/man-pages/man7/packet.7.html +pub mod eth { +    #[cfg(linux_kernel)] +    use { +        super::{new_raw_protocol, Protocol}, +        crate::backend::c, +    }; + +    /// `ETH_P_LOOP` +    #[cfg(linux_kernel)] +    pub const LOOP: Protocol = Protocol(new_raw_protocol((c::ETH_P_LOOP as u16).to_be() as u32)); +    /// `ETH_P_PUP` +    #[cfg(linux_kernel)] +    pub const PUP: Protocol = Protocol(new_raw_protocol((c::ETH_P_PUP as u16).to_be() as u32)); +    /// `ETH_P_PUPAT` +    #[cfg(linux_kernel)] +    pub const PUPAT: Protocol = Protocol(new_raw_protocol((c::ETH_P_PUPAT as u16).to_be() as u32)); +    /// `ETH_P_TSN` +    #[cfg(linux_kernel)] +    pub const TSN: Protocol = Protocol(new_raw_protocol((c::ETH_P_TSN as u16).to_be() as u32)); +    /// `ETH_P_ERSPAN2` +    #[cfg(linux_kernel)] +    pub const ERSPAN2: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ERSPAN2 as u16).to_be() as u32)); +    /// `ETH_P_IP` +    #[cfg(linux_kernel)] +    pub const IP: Protocol = Protocol(new_raw_protocol((c::ETH_P_IP as u16).to_be() as u32)); +    /// `ETH_P_X25` +    #[cfg(linux_kernel)] +    pub const X25: Protocol = Protocol(new_raw_protocol((c::ETH_P_X25 as u16).to_be() as u32)); +    /// `ETH_P_ARP` +    #[cfg(linux_kernel)] +    pub const ARP: Protocol = Protocol(new_raw_protocol((c::ETH_P_ARP as u16).to_be() as u32)); +    /// `ETH_P_BPQ` +    #[cfg(linux_kernel)] +    pub const BPQ: Protocol = Protocol(new_raw_protocol((c::ETH_P_BPQ as u16).to_be() as u32)); +    /// `ETH_P_IEEEPUP` +    #[cfg(linux_kernel)] +    pub const IEEEPUP: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_IEEEPUP as u16).to_be() as u32)); +    /// `ETH_P_IEEEPUPAT` +    #[cfg(linux_kernel)] +    pub const IEEEPUPAT: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_IEEEPUPAT as u16).to_be() as u32)); +    /// `ETH_P_BATMAN` +    #[cfg(linux_kernel)] +    pub const BATMAN: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_BATMAN as u16).to_be() as u32)); +    /// `ETH_P_DEC` +    #[cfg(linux_kernel)] +    pub const DEC: Protocol = Protocol(new_raw_protocol((c::ETH_P_DEC as u16).to_be() as u32)); +    /// `ETH_P_DNA_DL` +    #[cfg(linux_kernel)] +    pub const DNA_DL: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_DNA_DL as u16).to_be() as u32)); +    /// `ETH_P_DNA_RC` +    #[cfg(linux_kernel)] +    pub const DNA_RC: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_DNA_RC as u16).to_be() as u32)); +    /// `ETH_P_DNA_RT` +    #[cfg(linux_kernel)] +    pub const DNA_RT: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_DNA_RT as u16).to_be() as u32)); +    /// `ETH_P_LAT` +    #[cfg(linux_kernel)] +    pub const LAT: Protocol = Protocol(new_raw_protocol((c::ETH_P_LAT as u16).to_be() as u32)); +    /// `ETH_P_DIAG` +    #[cfg(linux_kernel)] +    pub const DIAG: Protocol = Protocol(new_raw_protocol((c::ETH_P_DIAG as u16).to_be() as u32)); +    /// `ETH_P_CUST` +    #[cfg(linux_kernel)] +    pub const CUST: Protocol = Protocol(new_raw_protocol((c::ETH_P_CUST as u16).to_be() as u32)); +    /// `ETH_P_SCA` +    #[cfg(linux_kernel)] +    pub const SCA: Protocol = Protocol(new_raw_protocol((c::ETH_P_SCA as u16).to_be() as u32)); +    /// `ETH_P_TEB` +    #[cfg(linux_kernel)] +    pub const TEB: Protocol = Protocol(new_raw_protocol((c::ETH_P_TEB as u16).to_be() as u32)); +    /// `ETH_P_RARP` +    #[cfg(linux_kernel)] +    pub const RARP: Protocol = Protocol(new_raw_protocol((c::ETH_P_RARP as u16).to_be() as u32)); +    /// `ETH_P_ATALK` +    #[cfg(linux_kernel)] +    pub const ATALK: Protocol = Protocol(new_raw_protocol((c::ETH_P_ATALK as u16).to_be() as u32)); +    /// `ETH_P_AARP` +    #[cfg(linux_kernel)] +    pub const AARP: Protocol = Protocol(new_raw_protocol((c::ETH_P_AARP as u16).to_be() as u32)); +    /// `ETH_P_8021Q` +    #[cfg(linux_kernel)] +    pub const P_8021Q: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_8021Q as u16).to_be() as u32)); +    /// `ETH_P_ERSPAN` +    #[cfg(linux_kernel)] +    pub const ERSPAN: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ERSPAN as u16).to_be() as u32)); +    /// `ETH_P_IPX` +    #[cfg(linux_kernel)] +    pub const IPX: Protocol = Protocol(new_raw_protocol((c::ETH_P_IPX as u16).to_be() as u32)); +    /// `ETH_P_IPV6` +    #[cfg(linux_kernel)] +    pub const IPV6: Protocol = Protocol(new_raw_protocol((c::ETH_P_IPV6 as u16).to_be() as u32)); +    /// `ETH_P_PAUSE` +    #[cfg(linux_kernel)] +    pub const PAUSE: Protocol = Protocol(new_raw_protocol((c::ETH_P_PAUSE as u16).to_be() as u32)); +    /// `ETH_P_SLOW` +    #[cfg(linux_kernel)] +    pub const SLOW: Protocol = Protocol(new_raw_protocol((c::ETH_P_SLOW as u16).to_be() as u32)); +    /// `ETH_P_WCCP` +    #[cfg(linux_kernel)] +    pub const WCCP: Protocol = Protocol(new_raw_protocol((c::ETH_P_WCCP as u16).to_be() as u32)); +    /// `ETH_P_MPLS_UC` +    #[cfg(linux_kernel)] +    pub const MPLS_UC: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_MPLS_UC as u16).to_be() as u32)); +    /// `ETH_P_MPLS_MC` +    #[cfg(linux_kernel)] +    pub const MPLS_MC: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_MPLS_MC as u16).to_be() as u32)); +    /// `ETH_P_ATMMPOA` +    #[cfg(linux_kernel)] +    pub const ATMMPOA: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ATMMPOA as u16).to_be() as u32)); +    /// `ETH_P_PPP_DISC` +    #[cfg(linux_kernel)] +    pub const PPP_DISC: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PPP_DISC as u16).to_be() as u32)); +    /// `ETH_P_PPP_SES` +    #[cfg(linux_kernel)] +    pub const PPP_SES: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PPP_SES as u16).to_be() as u32)); +    /// `ETH_P_LINK_CTL` +    #[cfg(linux_kernel)] +    pub const LINK_CTL: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_LINK_CTL as u16).to_be() as u32)); +    /// `ETH_P_ATMFATE` +    #[cfg(linux_kernel)] +    pub const ATMFATE: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ATMFATE as u16).to_be() as u32)); +    /// `ETH_P_PAE` +    #[cfg(linux_kernel)] +    pub const PAE: Protocol = Protocol(new_raw_protocol((c::ETH_P_PAE as u16).to_be() as u32)); +    /// `ETH_P_PROFINET` +    #[cfg(linux_kernel)] +    pub const PROFINET: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PROFINET as u16).to_be() as u32)); +    /// `ETH_P_REALTEK` +    #[cfg(linux_kernel)] +    pub const REALTEK: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_REALTEK as u16).to_be() as u32)); +    /// `ETH_P_AOE` +    #[cfg(linux_kernel)] +    pub const AOE: Protocol = Protocol(new_raw_protocol((c::ETH_P_AOE as u16).to_be() as u32)); +    /// `ETH_P_ETHERCAT` +    #[cfg(linux_kernel)] +    pub const ETHERCAT: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ETHERCAT as u16).to_be() as u32)); +    /// `ETH_P_8021AD` +    #[cfg(linux_kernel)] +    pub const P_8021AD: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_8021AD as u16).to_be() as u32)); +    /// `ETH_P_802_EX1` +    #[cfg(linux_kernel)] +    pub const P_802_EX1: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_802_EX1 as u16).to_be() as u32)); +    /// `ETH_P_PREAUTH` +    #[cfg(linux_kernel)] +    pub const PREAUTH: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PREAUTH as u16).to_be() as u32)); +    /// `ETH_P_TIPC` +    #[cfg(linux_kernel)] +    pub const TIPC: Protocol = Protocol(new_raw_protocol((c::ETH_P_TIPC as u16).to_be() as u32)); +    /// `ETH_P_LLDP` +    #[cfg(linux_kernel)] +    pub const LLDP: Protocol = Protocol(new_raw_protocol((c::ETH_P_LLDP as u16).to_be() as u32)); +    /// `ETH_P_MRP` +    #[cfg(linux_kernel)] +    pub const MRP: Protocol = Protocol(new_raw_protocol((c::ETH_P_MRP as u16).to_be() as u32)); +    /// `ETH_P_MACSEC` +    #[cfg(linux_kernel)] +    pub const MACSEC: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_MACSEC as u16).to_be() as u32)); +    /// `ETH_P_8021AH` +    #[cfg(linux_kernel)] +    pub const P_8021AH: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_8021AH as u16).to_be() as u32)); +    /// `ETH_P_MVRP` +    #[cfg(linux_kernel)] +    pub const MVRP: Protocol = Protocol(new_raw_protocol((c::ETH_P_MVRP as u16).to_be() as u32)); +    /// `ETH_P_1588` +    #[cfg(linux_kernel)] +    pub const P_1588: Protocol = Protocol(new_raw_protocol((c::ETH_P_1588 as u16).to_be() as u32)); +    /// `ETH_P_NCSI` +    #[cfg(linux_kernel)] +    pub const NCSI: Protocol = Protocol(new_raw_protocol((c::ETH_P_NCSI as u16).to_be() as u32)); +    /// `ETH_P_PRP` +    #[cfg(linux_kernel)] +    pub const PRP: Protocol = Protocol(new_raw_protocol((c::ETH_P_PRP as u16).to_be() as u32)); +    /// `ETH_P_CFM` +    #[cfg(linux_kernel)] +    pub const CFM: Protocol = Protocol(new_raw_protocol((c::ETH_P_CFM as u16).to_be() as u32)); +    /// `ETH_P_FCOE` +    #[cfg(linux_kernel)] +    pub const FCOE: Protocol = Protocol(new_raw_protocol((c::ETH_P_FCOE as u16).to_be() as u32)); +    /// `ETH_P_IBOE` +    #[cfg(linux_kernel)] +    pub const IBOE: Protocol = Protocol(new_raw_protocol((c::ETH_P_IBOE as u16).to_be() as u32)); +    /// `ETH_P_TDLS` +    #[cfg(linux_kernel)] +    pub const TDLS: Protocol = Protocol(new_raw_protocol((c::ETH_P_TDLS as u16).to_be() as u32)); +    /// `ETH_P_FIP` +    #[cfg(linux_kernel)] +    pub const FIP: Protocol = Protocol(new_raw_protocol((c::ETH_P_FIP as u16).to_be() as u32)); +    /// `ETH_P_80221` +    #[cfg(linux_kernel)] +    pub const P_80221: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_80221 as u16).to_be() as u32)); +    /// `ETH_P_HSR` +    #[cfg(linux_kernel)] +    pub const HSR: Protocol = Protocol(new_raw_protocol((c::ETH_P_HSR as u16).to_be() as u32)); +    /// `ETH_P_NSH` +    #[cfg(linux_kernel)] +    pub const NSH: Protocol = Protocol(new_raw_protocol((c::ETH_P_NSH as u16).to_be() as u32)); +    /// `ETH_P_LOOPBACK` +    #[cfg(linux_kernel)] +    pub const LOOPBACK: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_LOOPBACK as u16).to_be() as u32)); +    /// `ETH_P_QINQ1` +    #[cfg(linux_kernel)] +    pub const QINQ1: Protocol = Protocol(new_raw_protocol((c::ETH_P_QINQ1 as u16).to_be() as u32)); +    /// `ETH_P_QINQ2` +    #[cfg(linux_kernel)] +    pub const QINQ2: Protocol = Protocol(new_raw_protocol((c::ETH_P_QINQ2 as u16).to_be() as u32)); +    /// `ETH_P_QINQ3` +    #[cfg(linux_kernel)] +    pub const QINQ3: Protocol = Protocol(new_raw_protocol((c::ETH_P_QINQ3 as u16).to_be() as u32)); +    /// `ETH_P_EDSA` +    #[cfg(linux_kernel)] +    pub const EDSA: Protocol = Protocol(new_raw_protocol((c::ETH_P_EDSA as u16).to_be() as u32)); +    /// `ETH_P_DSA_8021Q` +    #[cfg(linux_kernel)] +    pub const DSA_8021Q: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_DSA_8021Q as u16).to_be() as u32)); +    /// `ETH_P_DSA_A5PSW` +    #[cfg(linux_kernel)] +    pub const DSA_A5PSW: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_DSA_A5PSW as u16).to_be() as u32)); +    /// `ETH_P_IFE` +    #[cfg(linux_kernel)] +    pub const IFE: Protocol = Protocol(new_raw_protocol((c::ETH_P_IFE as u16).to_be() as u32)); +    /// `ETH_P_AF_IUCV` +    #[cfg(linux_kernel)] +    pub const AF_IUCV: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_AF_IUCV as u16).to_be() as u32)); +    /// `ETH_P_802_3_MIN` +    #[cfg(linux_kernel)] +    pub const P_802_3_MIN: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_802_3_MIN as u16).to_be() as u32)); +    /// `ETH_P_802_3` +    #[cfg(linux_kernel)] +    pub const P_802_3: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_802_3 as u16).to_be() as u32)); +    /// `ETH_P_AX25` +    #[cfg(linux_kernel)] +    pub const AX25: Protocol = Protocol(new_raw_protocol((c::ETH_P_AX25 as u16).to_be() as u32)); +    /// `ETH_P_ALL` +    #[cfg(linux_kernel)] +    pub const ALL: Protocol = Protocol(new_raw_protocol((c::ETH_P_ALL as u16).to_be() as u32)); +    /// `ETH_P_802_2` +    #[cfg(linux_kernel)] +    pub const P_802_2: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_802_2 as u16).to_be() as u32)); +    /// `ETH_P_SNAP` +    #[cfg(linux_kernel)] +    pub const SNAP: Protocol = Protocol(new_raw_protocol((c::ETH_P_SNAP as u16).to_be() as u32)); +    /// `ETH_P_DDCMP` +    #[cfg(linux_kernel)] +    pub const DDCMP: Protocol = Protocol(new_raw_protocol((c::ETH_P_DDCMP as u16).to_be() as u32)); +    /// `ETH_P_WAN_PPP` +    #[cfg(linux_kernel)] +    pub const WAN_PPP: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_WAN_PPP as u16).to_be() as u32)); +    /// `ETH_P_PPP_MP` +    #[cfg(linux_kernel)] +    pub const PPP_MP: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PPP_MP as u16).to_be() as u32)); +    /// `ETH_P_LOCALTALK` +    #[cfg(linux_kernel)] +    pub const LOCALTALK: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_LOCALTALK as u16).to_be() as u32)); +    /// `ETH_P_CAN` +    #[cfg(linux_kernel)] +    pub const CAN: Protocol = Protocol(new_raw_protocol((c::ETH_P_CAN as u16).to_be() as u32)); +    /// `ETH_P_CANFD` +    #[cfg(linux_kernel)] +    pub const CANFD: Protocol = Protocol(new_raw_protocol((c::ETH_P_CANFD as u16).to_be() as u32)); +    /// `ETH_P_CANXL` +    #[cfg(linux_kernel)] +    pub const CANXL: Protocol = Protocol(new_raw_protocol((c::ETH_P_CANXL as u16).to_be() as u32)); +    /// `ETH_P_PPPTALK` +    #[cfg(linux_kernel)] +    pub const PPPTALK: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PPPTALK as u16).to_be() as u32)); +    /// `ETH_P_TR_802_2` +    #[cfg(linux_kernel)] +    pub const TR_802_2: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_TR_802_2 as u16).to_be() as u32)); +    /// `ETH_P_MOBITEX` +    #[cfg(linux_kernel)] +    pub const MOBITEX: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_MOBITEX as u16).to_be() as u32)); +    /// `ETH_P_CONTROL` +    #[cfg(linux_kernel)] +    pub const CONTROL: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_CONTROL as u16).to_be() as u32)); +    /// `ETH_P_IRDA` +    #[cfg(linux_kernel)] +    pub const IRDA: Protocol = Protocol(new_raw_protocol((c::ETH_P_IRDA as u16).to_be() as u32)); +    /// `ETH_P_ECONET` +    #[cfg(linux_kernel)] +    pub const ECONET: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ECONET as u16).to_be() as u32)); +    /// `ETH_P_HDLC` +    #[cfg(linux_kernel)] +    pub const HDLC: Protocol = Protocol(new_raw_protocol((c::ETH_P_HDLC as u16).to_be() as u32)); +    /// `ETH_P_ARCNET` +    #[cfg(linux_kernel)] +    pub const ARCNET: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_ARCNET as u16).to_be() as u32)); +    /// `ETH_P_DSA` +    #[cfg(linux_kernel)] +    pub const DSA: Protocol = Protocol(new_raw_protocol((c::ETH_P_DSA as u16).to_be() as u32)); +    /// `ETH_P_TRAILER` +    #[cfg(linux_kernel)] +    pub const TRAILER: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_TRAILER as u16).to_be() as u32)); +    /// `ETH_P_PHONET` +    #[cfg(linux_kernel)] +    pub const PHONET: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_PHONET as u16).to_be() as u32)); +    /// `ETH_P_IEEE802154` +    #[cfg(linux_kernel)] +    pub const IEEE802154: Protocol = +        Protocol(new_raw_protocol((c::ETH_P_IEEE802154 as u16).to_be() as u32)); +    /// `ETH_P_CAIF` +    #[cfg(linux_kernel)] +    pub const CAIF: Protocol = Protocol(new_raw_protocol((c::ETH_P_CAIF as u16).to_be() as u32)); +    /// `ETH_P_XDSA` +    #[cfg(linux_kernel)] +    pub const XDSA: Protocol = Protocol(new_raw_protocol((c::ETH_P_XDSA as u16).to_be() as u32)); +    /// `ETH_P_MAP` +    #[cfg(linux_kernel)] +    pub const MAP: Protocol = Protocol(new_raw_protocol((c::ETH_P_MAP as u16).to_be() as u32)); +    /// `ETH_P_MCTP` +    #[cfg(linux_kernel)] +    pub const MCTP: Protocol = Protocol(new_raw_protocol((c::ETH_P_MCTP as u16).to_be() as u32)); +} + +#[rustfmt::skip] +impl Protocol { +    /// 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_RD`—Disable further read operations. +    Read = c::SHUT_RD as _, +    /// `SHUT_WR`—Disable further write operations. +    Write = c::SHUT_WR as _, +    /// `SHUT_RDWR`—Disable further read and write operations. +    ReadWrite = c::SHUT_RDWR as _, +} + +bitflags! { +    /// `SOCK_*` constants for use with [`socket_with`], [`accept_with`] and +    /// [`acceptfrom_with`]. +    /// +    /// [`socket_with`]: crate::net::socket_with +    /// [`accept_with`]: crate::net::accept_with +    /// [`acceptfrom_with`]: crate::net::acceptfrom_with +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct SocketFlags: c::c_uint { +        /// `SOCK_NONBLOCK` +        #[cfg(not(any( +            apple, +            windows, +            target_os = "aix", +            target_os = "espidf", +            target_os = "haiku", +            target_os = "nto", +            target_os = "vita", +        )))] +        const NONBLOCK = bitcast!(c::SOCK_NONBLOCK); + +        /// `SOCK_CLOEXEC` +        #[cfg(not(any(apple, windows, target_os = "aix", target_os = "haiku")))] +        const CLOEXEC = bitcast!(c::SOCK_CLOEXEC); + +        // This deliberately lacks a `const _ = !0`, so that users can use +        // `from_bits_truncate` to extract the `SocketFlags` from a flags +        // value that also includes a `SocketType`. +    } +} + +/// UNIX credentials of socket peer, for use with [`get_socket_peercred`] +/// [`SendAncillaryMessage::ScmCredentials`] and +/// [`RecvAncillaryMessage::ScmCredentials`]. +/// +/// [`get_socket_peercred`]: crate::net::sockopt::get_socket_peercred +/// [`SendAncillaryMessage::ScmCredentials`]: crate::net::SendAncillaryMessage::ScmCredentials +/// [`RecvAncillaryMessage::ScmCredentials`]: crate::net::RecvAncillaryMessage::ScmCredentials +#[cfg(linux_kernel)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(C)] +pub struct UCred { +    /// Process ID of peer +    pub pid: crate::pid::Pid, +    /// User ID of peer +    pub uid: crate::ugid::Uid, +    /// Group ID of peer +    pub gid: crate::ugid::Gid, +} + +#[test] +fn test_sizes() { +    use c::c_int; +    use core::mem::transmute; + +    // Backend code needs to cast these to `c_int` so make sure that cast isn't +    // lossy. +    assert_eq_size!(RawProtocol, c_int); +    assert_eq_size!(Protocol, c_int); +    assert_eq_size!(Option<RawProtocol>, c_int); +    assert_eq_size!(Option<Protocol>, c_int); +    assert_eq_size!(RawSocketType, c_int); +    assert_eq_size!(SocketType, c_int); +    assert_eq_size!(SocketFlags, c_int); + +    // Rustix doesn't depend on `Option<Protocol>` matching the ABI of a raw +    // integer for correctness, but it should work nonetheless. +    #[allow(unsafe_code)] +    unsafe { +        let t: Option<Protocol> = None; +        assert_eq!(0_u32, transmute::<Option<Protocol>, u32>(t)); + +        let t: Option<Protocol> = Some(Protocol::from_raw(RawProtocol::new(4567).unwrap())); +        assert_eq!(4567_u32, transmute::<Option<Protocol>, u32>(t)); +    } + +    #[cfg(linux_kernel)] +    assert_eq_size!(UCred, libc::ucred); +} diff --git a/vendor/rustix/src/net/wsa.rs b/vendor/rustix/src/net/wsa.rs new file mode 100644 index 0000000..0ad4db5 --- /dev/null +++ b/vendor/rustix/src/net/wsa.rs @@ -0,0 +1,49 @@ +use crate::io; +use core::mem::MaybeUninit; +use windows_sys::Win32::Networking::WinSock::{WSACleanup, WSAGetLastError, WSAStartup, WSADATA}; + +/// `WSAStartup()`—Initialize process-wide Windows support for sockets. +/// +/// On Windows, it's necessary to initialize the sockets subsystem before +/// using sockets APIs. The function performs the necessary initialization. +/// +/// # References +///  - [Winsock] +/// +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup +pub fn wsa_startup() -> io::Result<WSADATA> { +    // Request version 2.2, which has been the latest version since far older +    // versions of Windows than we support here. For more information about +    // the version, see [here]. +    // +    // [here]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup#remarks +    let version = 0x202; +    let mut data = MaybeUninit::uninit(); +    unsafe { +        let ret = WSAStartup(version, data.as_mut_ptr()); +        if ret == 0 { +            Ok(data.assume_init()) +        } else { +            Err(io::Errno::from_raw_os_error(WSAGetLastError())) +        } +    } +} + +/// `WSACleanup()`—Clean up process-wide Windows support for sockets. +/// +/// In a program where `init` is called, if sockets are no longer necessary, +/// this function releases associated resources. +/// +/// # References +///  - [Winsock] +/// +/// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsacleanup +pub fn wsa_cleanup() -> io::Result<()> { +    unsafe { +        if WSACleanup() == 0 { +            Ok(()) +        } else { +            Err(io::Errno::from_raw_os_error(WSAGetLastError())) +        } +    } +}  | 
