From 4a1a9e2eeb63f980ec677d32041ba5e481331ba5 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sun, 28 Jan 2024 22:28:42 -0700 Subject: [PATCH 1/5] Add SocketAddrArg trait to reduce code duplicated across address types --- src/backend/libc/net/msghdr.rs | 99 +--- src/backend/libc/net/syscalls.rs | 238 ++------- src/backend/libc/net/write_sockaddr.rs | 62 +-- src/backend/linux_raw/net/msghdr.rs | 93 +--- src/backend/linux_raw/net/syscalls.rs | 504 ++++---------------- src/backend/linux_raw/net/write_sockaddr.rs | 53 +- src/net/addr.rs | 84 ++++ src/net/mod.rs | 1 + src/net/send_recv/mod.rs | 46 +- src/net/send_recv/msg.rs | 55 ++- src/net/socket.rs | 69 +-- src/net/socket_addr_any.rs | 24 +- src/net/types.rs | 17 + 13 files changed, 340 insertions(+), 1005 deletions(-) create mode 100644 src/net/addr.rs diff --git a/src/backend/libc/net/msghdr.rs b/src/backend/libc/net/msghdr.rs index d212c65a6..231129c14 100644 --- a/src/backend/libc/net/msghdr.rs +++ b/src/backend/libc/net/msghdr.rs @@ -5,15 +5,9 @@ use crate::backend::c; use crate::backend::conv::{msg_control_len, msg_iov_len}; -#[cfg(target_os = "linux")] -use crate::backend::net::write_sockaddr::encode_sockaddr_xdp; -use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; use crate::io::{self, IoSlice, IoSliceMut}; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; -use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6}; -use crate::utils::as_ptr; +use crate::net::{addr::SocketAddrArg, RecvAncillaryBuffer, SendAncillaryBuffer}; use core::mem::{size_of, zeroed, MaybeUninit}; @@ -66,87 +60,24 @@ pub(crate) fn with_noaddr_msghdr( }) } -/// Create a message header intended to send with an IPv4 address. -pub(crate) fn with_v4_msghdr( - addr: &SocketAddrV4, +/// Create a message header intended to send with the specified address. +pub(crate) fn with_msghdr( + addr: &impl SocketAddrArg, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, f: impl FnOnce(c::msghdr) -> R, ) -> R { - let encoded = encode_sockaddr_v4(addr); - - f({ - let mut h = zero_msghdr(); - h.msg_name = as_ptr(&encoded) as _; - h.msg_namelen = size_of::() as _; - h.msg_iov = iov.as_ptr() as _; - h.msg_iovlen = msg_iov_len(iov.len()); - h.msg_control = control.as_control_ptr().cast(); - h.msg_controllen = msg_control_len(control.control_len()); - h - }) -} - -/// Create a message header intended to send with an IPv6 address. -pub(crate) fn with_v6_msghdr( - addr: &SocketAddrV6, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - let encoded = encode_sockaddr_v6(addr); - - f({ - let mut h = zero_msghdr(); - h.msg_name = as_ptr(&encoded) as _; - h.msg_namelen = size_of::() as _; - h.msg_iov = iov.as_ptr() as _; - h.msg_iovlen = msg_iov_len(iov.len()); - h.msg_control = control.as_control_ptr().cast(); - h.msg_controllen = msg_control_len(control.control_len()); - h - }) -} - -/// Create a message header intended to send with a Unix address. -#[cfg(all(unix, not(target_os = "redox")))] -pub(crate) fn with_unix_msghdr( - addr: &crate::net::SocketAddrUnix, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - f({ - let mut h = zero_msghdr(); - h.msg_name = as_ptr(&addr.unix) as _; - h.msg_namelen = addr.addr_len(); - h.msg_iov = iov.as_ptr() as _; - h.msg_iovlen = msg_iov_len(iov.len()); - h.msg_control = control.as_control_ptr().cast(); - h.msg_controllen = msg_control_len(control.control_len()); - h - }) -} - -/// Create a message header intended to send with an IPv6 address. -#[cfg(target_os = "linux")] -pub(crate) fn with_xdp_msghdr( - addr: &SocketAddrXdp, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - let encoded = encode_sockaddr_xdp(addr); - - f({ - let mut h = zero_msghdr(); - h.msg_name = as_ptr(&encoded) as _; - h.msg_namelen = size_of::() as _; - h.msg_iov = iov.as_ptr() as _; - h.msg_iovlen = msg_iov_len(iov.len()); - h.msg_control = control.as_control_ptr().cast(); - h.msg_controllen = msg_control_len(control.control_len()); - h + addr.with_sockaddr(|addr_ptr, addr_len| { + f({ + let mut h = zero_msghdr(); + h.msg_name = addr_ptr as *mut _; + h.msg_namelen = addr_len as c::socklen_t; + h.msg_iov = iov.as_ptr() as _; + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }) }) } diff --git a/src/backend/libc/net/syscalls.rs b/src/backend/libc/net/syscalls.rs index d08bfca15..438fadb53 100644 --- a/src/backend/libc/net/syscalls.rs +++ b/src/backend/libc/net/syscalls.rs @@ -1,32 +1,21 @@ //! libc syscalls supporting `rustix::net`. -#[cfg(unix)] -use super::addr::SocketAddrUnix; -#[cfg(target_os = "linux")] -use super::msghdr::with_xdp_msghdr; use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; -#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "vita")))] -use super::send_recv::ReturnFlags; use super::send_recv::{RecvFlags, SendFlags}; -#[cfg(target_os = "linux")] -use super::write_sockaddr::encode_sockaddr_xdp; -use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; use crate::backend::c; use crate::backend::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; use crate::net::{ - AddressFamily, Protocol, Shutdown, SocketAddrAny, SocketAddrV4, SocketAddrV6, SocketFlags, - SocketType, + addr::SocketAddrArg, AddressFamily, Protocol, Shutdown, SocketAddrAny, SocketFlags, SocketType, }; use crate::utils::as_ptr; use core::mem::{size_of, MaybeUninit}; use core::ptr::null_mut; #[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "vita")))] use { - super::msghdr::{with_noaddr_msghdr, with_recv_msghdr, with_v4_msghdr, with_v6_msghdr}, + super::msghdr::{with_msghdr, with_noaddr_msghdr, with_recv_msghdr}, + super::send_recv::ReturnFlags, crate::io::{IoSlice, IoSliceMut}, crate::net::{RecvAncillaryBuffer, RecvMsg, SendAncillaryBuffer}, }; @@ -86,77 +75,23 @@ pub(crate) unsafe fn recvfrom( }) } -pub(crate) fn sendto_v4( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV4, -) -> io::Result { - unsafe { - ret_send_recv(c::sendto( - borrowed_fd(fd), - buf.as_ptr().cast(), - send_recv_len(buf.len()), - bitflags_bits!(flags), - as_ptr(&encode_sockaddr_v4(addr)).cast::(), - size_of::() as c::socklen_t, - )) - } -} - -pub(crate) fn sendto_v6( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV6, -) -> io::Result { - unsafe { - ret_send_recv(c::sendto( - borrowed_fd(fd), - buf.as_ptr().cast(), - send_recv_len(buf.len()), - bitflags_bits!(flags), - as_ptr(&encode_sockaddr_v6(addr)).cast::(), - size_of::() as c::socklen_t, - )) - } -} - -#[cfg(not(windows))] -pub(crate) fn sendto_unix( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrUnix, -) -> io::Result { - unsafe { - ret_send_recv(c::sendto( - borrowed_fd(fd), - buf.as_ptr().cast(), - send_recv_len(buf.len()), - bitflags_bits!(flags), - as_ptr(&addr.unix).cast(), - addr.addr_len(), - )) - } -} - -#[cfg(target_os = "linux")] -pub(crate) fn sendto_xdp( +pub(crate) fn sendto( fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags, - addr: &SocketAddrXdp, + addr: &impl SocketAddrArg, ) -> io::Result { unsafe { - ret_send_recv(c::sendto( - borrowed_fd(fd), - buf.as_ptr().cast(), - send_recv_len(buf.len()), - bitflags_bits!(flags), - as_ptr(&encode_sockaddr_xdp(addr)).cast::(), - size_of::() as _, - )) + addr.with_sockaddr(|addr_ptr, addr_len| { + ret_send_recv(c::sendto( + borrowed_fd(fd), + buf.as_ptr().cast(), + send_recv_len(buf.len()), + bitflags_bits!(flags), + addr_ptr.cast(), + addr_len as c::socklen_t, + )) + }) } } @@ -197,76 +132,27 @@ pub(crate) fn socket_with( } } -pub(crate) fn bind_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { - unsafe { - ret(c::bind( - borrowed_fd(sockfd), - as_ptr(&encode_sockaddr_v4(addr)).cast(), - size_of::() as c::socklen_t, - )) - } -} - -pub(crate) fn bind_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { +pub(crate) fn bind(sockfd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> { unsafe { - ret(c::bind( - borrowed_fd(sockfd), - as_ptr(&encode_sockaddr_v6(addr)).cast(), - size_of::() as c::socklen_t, - )) - } -} - -#[cfg(not(windows))] -pub(crate) fn bind_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { - unsafe { - ret(c::bind( - borrowed_fd(sockfd), - as_ptr(&addr.unix).cast(), - addr.addr_len(), - )) - } -} - -#[cfg(target_os = "linux")] -pub(crate) fn bind_xdp(sockfd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> { - unsafe { - ret(c::bind( - borrowed_fd(sockfd), - as_ptr(&encode_sockaddr_xdp(addr)).cast(), - size_of::() as c::socklen_t, - )) - } -} - -pub(crate) fn connect_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { - unsafe { - ret(c::connect( - borrowed_fd(sockfd), - as_ptr(&encode_sockaddr_v4(addr)).cast(), - size_of::() as c::socklen_t, - )) - } -} - -pub(crate) fn connect_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { - unsafe { - ret(c::connect( - borrowed_fd(sockfd), - as_ptr(&encode_sockaddr_v6(addr)).cast(), - size_of::() as c::socklen_t, - )) + addr.with_sockaddr(|addr_ptr, addr_len| { + ret(c::bind( + borrowed_fd(sockfd), + addr_ptr.cast(), + addr_len as c::socklen_t, + )) + }) } } -#[cfg(not(windows))] -pub(crate) fn connect_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { +pub(crate) fn connect(sockfd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> { unsafe { - ret(c::connect( - borrowed_fd(sockfd), - as_ptr(&addr.unix).cast(), - addr.addr_len(), - )) + addr.with_sockaddr(|addr_ptr, addr_len| { + ret(c::connect( + borrowed_fd(sockfd), + addr_ptr.cast(), + addr_len as c::socklen_t, + )) + }) } } @@ -341,69 +227,15 @@ pub(crate) fn sendmsg( }) } -#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "vita")))] -pub(crate) fn sendmsg_v4( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrV4, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - with_v4_msghdr(addr, iov, control, |msghdr| unsafe { - ret_send_recv(c::sendmsg( - borrowed_fd(sockfd), - &msghdr, - bitflags_bits!(msg_flags), - )) - }) -} - -#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "vita")))] -pub(crate) fn sendmsg_v6( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrV6, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - with_v6_msghdr(addr, iov, control, |msghdr| unsafe { - ret_send_recv(c::sendmsg( - borrowed_fd(sockfd), - &msghdr, - bitflags_bits!(msg_flags), - )) - }) -} - -#[cfg(all( - unix, - not(any(target_os = "espidf", target_os = "redox", target_os = "vita")) -))] -pub(crate) fn sendmsg_unix( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrUnix, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - super::msghdr::with_unix_msghdr(addr, iov, control, |msghdr| unsafe { - ret_send_recv(c::sendmsg( - borrowed_fd(sockfd), - &msghdr, - bitflags_bits!(msg_flags), - )) - }) -} - -#[cfg(target_os = "linux")] -pub(crate) fn sendmsg_xdp( +#[cfg(not(any(windows, target_os = "espidf", target_os = "redox", target_os = "vita",)))] +pub(crate) fn sendmsg_addr( sockfd: BorrowedFd<'_>, - addr: &SocketAddrXdp, + addr: &impl SocketAddrArg, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, msg_flags: SendFlags, ) -> io::Result { - with_xdp_msghdr(addr, iov, control, |msghdr| unsafe { + with_msghdr(addr, iov, control, |msghdr| unsafe { ret_send_recv(c::sendmsg( borrowed_fd(sockfd), &msghdr, diff --git a/src/backend/libc/net/write_sockaddr.rs b/src/backend/libc/net/write_sockaddr.rs index afc95385a..08f04646c 100644 --- a/src/backend/libc/net/write_sockaddr.rs +++ b/src/backend/libc/net/write_sockaddr.rs @@ -1,29 +1,9 @@ //! The BSD sockets API requires us to read the `sa_family` field before we can //! interpret the rest of a `sockaddr` produced by the kernel. -use super::addr::SocketAddrStorage; -#[cfg(unix)] -use super::addr::SocketAddrUnix; use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new}; use crate::backend::c; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; -use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6}; -use core::mem::size_of; - -pub(crate) unsafe fn write_sockaddr( - addr: &SocketAddrAny, - storage: *mut SocketAddrStorage, -) -> usize { - match addr { - SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage), - SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage), - #[cfg(unix)] - SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage), - #[cfg(target_os = "linux")] - SocketAddrAny::Xdp(xdp) => write_sockaddr_xdp(xdp, storage), - } -} +use crate::net::{SocketAddrV4, SocketAddrV6}; pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in { c::sockaddr_in { @@ -36,7 +16,7 @@ pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in { target_os = "nto", target_os = "vita", ))] - sin_len: size_of::() as _, + sin_len: core::mem::size_of::() as _, sin_family: c::AF_INET as _, sin_port: u16::to_be(v4.port()), sin_addr: in_addr_new(u32::from_ne_bytes(v4.ip().octets())), @@ -51,12 +31,6 @@ pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in { } } -unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_v4(v4); - core::ptr::write(storage.cast(), encoded); - size_of::() -} - pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { #[cfg(any( bsd, @@ -69,7 +43,7 @@ pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { ))] { sockaddr_in6_new( - size_of::() as _, + core::mem::size_of::() as _, c::AF_INET6 as _, u16::to_be(v6.port()), u32::to_be(v6.flowinfo()), @@ -96,33 +70,3 @@ pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { ) } } - -unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_v6(v6); - core::ptr::write(storage.cast(), encoded); - size_of::() -} - -#[cfg(unix)] -unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize { - core::ptr::write(storage.cast(), unix.unix); - unix.len() -} - -#[cfg(target_os = "linux")] -pub(crate) fn encode_sockaddr_xdp(xdp: &SocketAddrXdp) -> c::sockaddr_xdp { - c::sockaddr_xdp { - sxdp_family: c::AF_XDP as _, - sxdp_flags: xdp.flags().bits(), - sxdp_ifindex: xdp.interface_index(), - sxdp_queue_id: xdp.queue_id(), - sxdp_shared_umem_fd: xdp.shared_umem_fd(), - } -} - -#[cfg(target_os = "linux")] -unsafe fn write_sockaddr_xdp(xdp: &SocketAddrXdp, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_xdp(xdp); - core::ptr::write(storage.cast(), encoded); - size_of::() -} diff --git a/src/backend/linux_raw/net/msghdr.rs b/src/backend/linux_raw/net/msghdr.rs index 3ccce04c9..8734fd5f9 100644 --- a/src/backend/linux_raw/net/msghdr.rs +++ b/src/backend/linux_raw/net/msghdr.rs @@ -6,15 +6,9 @@ #![allow(unsafe_code)] use crate::backend::c; -#[cfg(target_os = "linux")] -use crate::backend::net::write_sockaddr::encode_sockaddr_xdp; -use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; use crate::io::{self, IoSlice, IoSliceMut}; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; -use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6}; -use crate::utils::as_ptr; +use crate::net::{addr::SocketAddrArg, RecvAncillaryBuffer, SendAncillaryBuffer}; use core::mem::{size_of, MaybeUninit}; use core::ptr::null_mut; @@ -78,82 +72,23 @@ pub(crate) fn with_noaddr_msghdr( }) } -/// Create a message header intended to send with an IPv4 address. -pub(crate) fn with_v4_msghdr( - addr: &SocketAddrV4, +/// Create a message header intended to send with the specified address +pub(crate) fn with_msghdr( + addr: &impl SocketAddrArg, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, f: impl FnOnce(c::msghdr) -> R, ) -> R { - let encoded = encode_sockaddr_v4(addr); - - f(c::msghdr { - msg_name: as_ptr(&encoded) as _, - msg_namelen: size_of::() as _, - msg_iov: iov.as_ptr() as _, - msg_iovlen: msg_iov_len(iov.len()), - msg_control: control.as_control_ptr().cast(), - msg_controllen: msg_control_len(control.control_len()), - msg_flags: 0, - }) -} - -/// Create a message header intended to send with an IPv6 address. -pub(crate) fn with_v6_msghdr( - addr: &SocketAddrV6, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - let encoded = encode_sockaddr_v6(addr); - - f(c::msghdr { - msg_name: as_ptr(&encoded) as _, - msg_namelen: size_of::() as _, - msg_iov: iov.as_ptr() as _, - msg_iovlen: msg_iov_len(iov.len()), - msg_control: control.as_control_ptr().cast(), - msg_controllen: msg_control_len(control.control_len()), - msg_flags: 0, - }) -} - -/// Create a message header intended to send with a Unix address. -pub(crate) fn with_unix_msghdr( - addr: &crate::net::SocketAddrUnix, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - f(c::msghdr { - msg_name: as_ptr(&addr.unix) as _, - msg_namelen: addr.addr_len() as _, - msg_iov: iov.as_ptr() as _, - msg_iovlen: msg_iov_len(iov.len()), - msg_control: control.as_control_ptr().cast(), - msg_controllen: msg_control_len(control.control_len()), - msg_flags: 0, - }) -} - -/// Create a message header intended to send with an XDP address. -#[cfg(target_os = "linux")] -pub(crate) fn with_xdp_msghdr( - addr: &SocketAddrXdp, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - f: impl FnOnce(c::msghdr) -> R, -) -> R { - let encoded = encode_sockaddr_xdp(addr); - - f(c::msghdr { - msg_name: as_ptr(&encoded) as _, - msg_namelen: size_of::() as _, - msg_iov: iov.as_ptr() as _, - msg_iovlen: msg_iov_len(iov.len()), - msg_control: control.as_control_ptr().cast(), - msg_controllen: msg_control_len(control.control_len()), - msg_flags: 0, + addr.with_sockaddr(|addr_ptr, addr_len| { + f(c::msghdr { + msg_name: addr_ptr as _, + msg_namelen: addr_len as _, + msg_iov: iov.as_ptr() as _, + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + msg_flags: 0, + }) }) } diff --git a/src/backend/linux_raw/net/syscalls.rs b/src/backend/linux_raw/net/syscalls.rs index c9e1fa299..f239016ba 100644 --- a/src/backend/linux_raw/net/syscalls.rs +++ b/src/backend/linux_raw/net/syscalls.rs @@ -5,30 +5,22 @@ //! See the `rustix::backend` module documentation for details. #![allow(unsafe_code, clippy::undocumented_unsafe_blocks)] -#[cfg(target_os = "linux")] -use super::msghdr::with_xdp_msghdr; -use super::msghdr::{ - with_noaddr_msghdr, with_recv_msghdr, with_unix_msghdr, with_v4_msghdr, with_v6_msghdr, -}; +use super::msghdr::{with_msghdr, with_noaddr_msghdr, with_recv_msghdr}; use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; use super::send_recv::{RecvFlags, ReturnFlags, SendFlags}; -#[cfg(target_os = "linux")] -use super::write_sockaddr::encode_sockaddr_xdp; -use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; use crate::backend::c; use crate::backend::conv::{ by_mut, by_ref, c_int, c_uint, pass_usize, ret, ret_owned_fd, ret_usize, size_of, slice, socklen_t, zero, }; +use crate::backend::reg::raw_arg; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io::{self, IoSlice, IoSliceMut}; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; use crate::net::{ - AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsg, SendAncillaryBuffer, Shutdown, - SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6, SocketFlags, SocketType, + addr::SocketAddrArg, AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsg, + SendAncillaryBuffer, Shutdown, SocketAddrAny, SocketFlags, SocketType, }; -use c::{sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t}; +use c::{sockaddr_storage, socklen_t}; use core::mem::MaybeUninit; #[cfg(target_arch = "x86")] use { @@ -329,14 +321,14 @@ pub(crate) fn sendmsg( } #[inline] -pub(crate) fn sendmsg_v4( +pub(crate) fn sendmsg_addr( sockfd: BorrowedFd<'_>, - addr: &SocketAddrV4, + addr: &impl SocketAddrArg, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, msg_flags: SendFlags, ) -> io::Result { - with_v4_msghdr(addr, iov, control, |msghdr| { + with_msghdr(addr, iov, control, |msghdr| { #[cfg(not(target_arch = "x86"))] let result = unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; @@ -358,97 +350,6 @@ pub(crate) fn sendmsg_v4( }) } -#[inline] -pub(crate) fn sendmsg_v6( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrV6, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - with_v6_msghdr(addr, iov, control, |msghdr| { - #[cfg(not(target_arch = "x86"))] - let result = - unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; - - #[cfg(target_arch = "x86")] - let result = unsafe { - ret_usize(syscall!( - __NR_socketcall, - x86_sys(SYS_SENDMSG), - slice_just_addr::, _>(&[ - sockfd.into(), - by_ref(&msghdr), - msg_flags.into() - ]) - )) - }; - - result - }) -} - -#[inline] -pub(crate) fn sendmsg_unix( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrUnix, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - with_unix_msghdr(addr, iov, control, |msghdr| { - #[cfg(not(target_arch = "x86"))] - let result = - unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; - - #[cfg(target_arch = "x86")] - let result = unsafe { - ret_usize(syscall!( - __NR_socketcall, - x86_sys(SYS_SENDMSG), - slice_just_addr::, _>(&[ - sockfd.into(), - by_ref(&msghdr), - msg_flags.into() - ]) - )) - }; - - result - }) -} - -#[cfg(target_os = "linux")] -#[inline] -pub(crate) fn sendmsg_xdp( - sockfd: BorrowedFd<'_>, - addr: &SocketAddrXdp, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - msg_flags: SendFlags, -) -> io::Result { - with_xdp_msghdr(addr, iov, control, |msghdr| { - #[cfg(not(target_arch = "x86"))] - let result = - unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; - - #[cfg(target_arch = "x86")] - let result = unsafe { - ret_usize(syscall!( - __NR_socketcall, - x86_sys(SYS_SENDMSG), - slice_just_addr::, _>(&[ - sockfd.into(), - by_ref(&msghdr), - msg_flags.into() - ]) - )) - }; - - result - }) -} - #[inline] pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> { #[cfg(not(target_arch = "x86"))] @@ -520,156 +421,43 @@ pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Resu } #[inline] -pub(crate) fn sendto_v4( +pub(crate) fn sendto( fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags, - addr: &SocketAddrV4, + addr: &impl SocketAddrArg, ) -> io::Result { let (buf_addr, buf_len) = slice(buf); - #[cfg(not(target_arch = "x86"))] - unsafe { - ret_usize(syscall_readonly!( - __NR_sendto, - fd, - buf_addr, - buf_len, - flags, - by_ref(&encode_sockaddr_v4(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret_usize(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_SENDTO), - slice_just_addr::, _>(&[ - fd.into(), - buf_addr, - buf_len, - flags.into(), - by_ref(&encode_sockaddr_v4(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn sendto_v6( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV6, -) -> io::Result { - let (buf_addr, buf_len) = slice(buf); - - #[cfg(not(target_arch = "x86"))] - unsafe { - ret_usize(syscall_readonly!( - __NR_sendto, - fd, - buf_addr, - buf_len, - flags, - by_ref(&encode_sockaddr_v6(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret_usize(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_SENDTO), - slice_just_addr::, _>(&[ - fd.into(), - buf_addr, - buf_len, - flags.into(), - by_ref(&encode_sockaddr_v6(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn sendto_unix( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrUnix, -) -> io::Result { - let (buf_addr, buf_len) = slice(buf); - - #[cfg(not(target_arch = "x86"))] - unsafe { - ret_usize(syscall_readonly!( - __NR_sendto, - fd, - buf_addr, - buf_len, - flags, - by_ref(&addr.unix), - socklen_t(addr.addr_len()) - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret_usize(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_SENDTO), - slice_just_addr::, _>(&[ - fd.into(), - buf_addr, - buf_len, - flags.into(), - by_ref(&addr.unix), - socklen_t(addr.addr_len()), - ]) - )) - } -} - -#[cfg(target_os = "linux")] -#[inline] -pub(crate) fn sendto_xdp( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrXdp, -) -> io::Result { - let (buf_addr, buf_len) = slice(buf); - - #[cfg(not(target_arch = "x86"))] - unsafe { - ret_usize(syscall_readonly!( - __NR_sendto, - fd, - buf_addr, - buf_len, - flags, - by_ref(&encode_sockaddr_xdp(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret_usize(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_SENDTO), - slice_just_addr::, _>(&[ - fd.into(), + addr.with_sockaddr(|addr_ptr, addr_len| { + #[cfg(not(target_arch = "x86"))] + unsafe { + ret_usize(syscall_readonly!( + __NR_sendto, + fd, buf_addr, buf_len, - flags.into(), - by_ref(&encode_sockaddr_xdp(addr)), - size_of::(), - ]) - )) - } + flags, + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + )) + } + #[cfg(target_arch = "x86")] + unsafe { + ret_usize(syscall_readonly!( + __NR_socketcall, + x86_sys(SYS_SENDTO), + slice_just_addr::, _>(&[ + fd.into(), + buf_addr, + buf_len, + flags.into(), + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + ]) + )) + } + }) } #[inline] @@ -845,179 +633,57 @@ pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result { } #[inline] -pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_bind, - fd, - by_ref(&encode_sockaddr_v4(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_BIND), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&encode_sockaddr_v4(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_bind, - fd, - by_ref(&encode_sockaddr_v6(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_BIND), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&encode_sockaddr_v6(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_bind, - fd, - by_ref(&addr.unix), - socklen_t(addr.addr_len()) - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_BIND), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&addr.unix), - socklen_t(addr.addr_len()), - ]) - )) - } -} - -#[cfg(target_os = "linux")] -#[inline] -pub(crate) fn bind_xdp(fd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_bind, - fd, - by_ref(&encode_sockaddr_xdp(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_BIND), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&encode_sockaddr_xdp(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_connect, - fd, - by_ref(&encode_sockaddr_v4(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_CONNECT), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&encode_sockaddr_v4(addr)), - size_of::(), - ]) - )) - } -} - -#[inline] -pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_connect, - fd, - by_ref(&encode_sockaddr_v6(addr)), - size_of::() - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_CONNECT), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&encode_sockaddr_v6(addr)), - size_of::(), - ]) - )) - } +pub(crate) fn bind(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> { + addr.with_sockaddr(|addr_ptr, addr_len| { + #[cfg(not(target_arch = "x86"))] + unsafe { + ret(syscall_readonly!( + __NR_bind, + fd, + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + )) + } + #[cfg(target_arch = "x86")] + unsafe { + ret(syscall_readonly!( + __NR_socketcall, + x86_sys(SYS_BIND), + slice_just_addr::, _>(&[ + fd.into(), + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + ]) + )) + } + }) } #[inline] -pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { - #[cfg(not(target_arch = "x86"))] - unsafe { - ret(syscall_readonly!( - __NR_connect, - fd, - by_ref(&addr.unix), - socklen_t(addr.addr_len()) - )) - } - #[cfg(target_arch = "x86")] - unsafe { - ret(syscall_readonly!( - __NR_socketcall, - x86_sys(SYS_CONNECT), - slice_just_addr::, _>(&[ - fd.into(), - by_ref(&addr.unix), - socklen_t(addr.addr_len()), - ]) - )) - } +pub(crate) fn connect(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> { + addr.with_sockaddr(|addr_ptr, addr_len| { + #[cfg(not(target_arch = "x86"))] + unsafe { + ret(syscall_readonly!( + __NR_connect, + fd, + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + )) + } + #[cfg(target_arch = "x86")] + unsafe { + ret(syscall_readonly!( + __NR_socketcall, + x86_sys(SYS_CONNECT), + slice_just_addr::, _>(&[ + fd.into(), + raw_arg(addr_ptr as *mut _), + socklen_t(addr_len as socklen_t) + ]) + )) + } + }) } #[inline] diff --git a/src/backend/linux_raw/net/write_sockaddr.rs b/src/backend/linux_raw/net/write_sockaddr.rs index b637c5d23..3b348221a 100644 --- a/src/backend/linux_raw/net/write_sockaddr.rs +++ b/src/backend/linux_raw/net/write_sockaddr.rs @@ -3,23 +3,7 @@ #![allow(unsafe_code)] use crate::backend::c; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; -use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; -use core::mem::size_of; - -pub(crate) unsafe fn write_sockaddr( - addr: &SocketAddrAny, - storage: *mut SocketAddrStorage, -) -> usize { - match addr { - SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage), - SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage), - SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage), - #[cfg(target_os = "linux")] - SocketAddrAny::Xdp(xdp) => write_sockaddr_xdp(xdp, storage), - } -} +use crate::net::{SocketAddrV4, SocketAddrV6}; pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in { c::sockaddr_in { @@ -32,12 +16,6 @@ pub(crate) fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in { } } -unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_v4(v4); - core::ptr::write(storage.cast(), encoded); - size_of::() -} - pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { c::sockaddr_in6 { sin6_family: c::AF_INET6 as _, @@ -51,32 +29,3 @@ pub(crate) fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { sin6_scope_id: v6.scope_id(), } } - -unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_v6(v6); - core::ptr::write(storage.cast(), encoded); - size_of::() -} - -unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize { - core::ptr::write(storage.cast(), unix.unix); - unix.len() -} - -#[cfg(target_os = "linux")] -pub(crate) fn encode_sockaddr_xdp(xdp: &SocketAddrXdp) -> c::sockaddr_xdp { - c::sockaddr_xdp { - sxdp_family: c::AF_XDP as _, - sxdp_flags: xdp.flags().bits(), - sxdp_ifindex: xdp.interface_index(), - sxdp_queue_id: xdp.queue_id(), - sxdp_shared_umem_fd: xdp.shared_umem_fd(), - } -} - -#[cfg(target_os = "linux")] -unsafe fn write_sockaddr_xdp(xdp: &SocketAddrXdp, storage: *mut SocketAddrStorage) -> usize { - let encoded = encode_sockaddr_xdp(xdp); - core::ptr::write(storage.cast(), encoded); - size_of::() -} diff --git a/src/net/addr.rs b/src/net/addr.rs new file mode 100644 index 000000000..36b3fe6aa --- /dev/null +++ b/src/net/addr.rs @@ -0,0 +1,84 @@ +//! Types for implementers of socket address types or code that is generic over +//! address types. +//! +//! The concrete address types and [`SocketAddrAny`] are in [the parent module][`super`]. + +#![allow(unsafe_code)] +use core::mem::size_of; + +use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; + +use super::{SocketAddr, SocketAddrV4, SocketAddrV6}; + +#[cfg(unix)] +use super::SocketAddrUnix; + +/// Opaque type equivalent to `sockaddr` in C. +/// +/// This is always used behind a raw pointer that is cast from a pointer to a +/// `sockaddr`-compatible C type, and then cast back to a `sockaddr` pointer +/// to be passed to a system call. +#[repr(C)] +pub struct SocketAddrOpaque { + _data: [u8; 0], +} + +/// A trait abstracting over the types that can be passed as a `sockaddr`. +/// +/// # Safety +/// Implementers of this trait must ensure that `with_sockaddr` calls +/// `f` with a pointer that is readable for the passed length, and points +/// to data that is a valid socket address for the system calls that accept +/// `sockaddr` as a const pointer. +pub unsafe trait SocketAddrArg { + /// Call a closure with the pointer and length to the corresponding C type. + /// + /// The API uses a closure so that: + /// * The libc types are not exposed in the rustix API. + /// * Types like `SocketAddrUnix` that contain their corresponding + /// C type can pass it directly without a copy. + /// * Other socket types can construct their C-compatible struct on the + /// stack and call the closure with a pointer to it. + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R; +} + +/// Helper for implementing SocketAddrArg::with_sockaddr +pub(crate) fn call_with_sockaddr( + addr: &A, + f: impl FnOnce(*const SocketAddrOpaque, usize) -> R, +) -> R { + let ptr = (addr as *const A).cast(); + let len = size_of::(); + f(ptr, len) +} + +unsafe impl SocketAddrArg for super::SocketAddr { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + match self { + SocketAddr::V4(v4) => v4.with_sockaddr(f), + SocketAddr::V6(v6) => v6.with_sockaddr(f), + } + } +} + +unsafe impl SocketAddrArg for SocketAddrV4 { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + call_with_sockaddr(&encode_sockaddr_v4(self), f) + } +} + +unsafe impl SocketAddrArg for SocketAddrV6 { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + call_with_sockaddr(&encode_sockaddr_v6(self), f) + } +} + +#[cfg(unix)] +unsafe impl SocketAddrArg for SocketAddrUnix { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + f( + (&self.unix as *const crate::backend::c::sockaddr_un).cast(), + self.addr_len() as usize, + ) + } +} diff --git a/src/net/mod.rs b/src/net/mod.rs index 7ec8bc698..05d62bd6d 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -7,6 +7,7 @@ //! [`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 +pub mod addr; mod send_recv; mod socket; mod socket_addr_any; diff --git a/src/net/send_recv/mod.rs b/src/net/send_recv/mod.rs index 4f5cf44ea..41cd48538 100644 --- a/src/net/send_recv/mod.rs +++ b/src/net/send_recv/mod.rs @@ -7,9 +7,9 @@ use crate::buffer::split_init; use crate::net::xdp::SocketAddrXdp; #[cfg(unix)] use crate::net::SocketAddrUnix; -use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::net::{addr::SocketAddrArg, SocketAddrAny, SocketAddrV4, SocketAddrV6}; use crate::{backend, io}; -use backend::fd::{AsFd, BorrowedFd}; +use backend::fd::AsFd; use core::cmp::min; use core::mem::MaybeUninit; @@ -213,21 +213,9 @@ pub fn sendto( fd: Fd, buf: &[u8], flags: SendFlags, - addr: &SocketAddr, + addr: &impl SocketAddrArg, ) -> io::Result { - _sendto(fd.as_fd(), buf, flags, addr) -} - -fn _sendto( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddr, -) -> io::Result { - 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), - } + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } /// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific @@ -263,23 +251,7 @@ pub fn sendto_any( flags: SendFlags, addr: &SocketAddrAny, ) -> io::Result { - _sendto_any(fd.as_fd(), buf, flags, addr) -} - -fn _sendto_any( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrAny, -) -> io::Result { - 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), - #[cfg(target_os = "linux")] - SocketAddrAny::Xdp(xdp) => backend::net::syscalls::sendto_xdp(fd, buf, flags, xdp), - } + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } /// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to @@ -317,7 +289,7 @@ pub fn sendto_v4( flags: SendFlags, addr: &SocketAddrV4, ) -> io::Result { - backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr) + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } /// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data @@ -355,7 +327,7 @@ pub fn sendto_v6( flags: SendFlags, addr: &SocketAddrV6, ) -> io::Result { - backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr) + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } /// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to @@ -394,7 +366,7 @@ pub fn sendto_unix( flags: SendFlags, addr: &SocketAddrUnix, ) -> io::Result { - backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr) + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } /// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_xdp))`—Writes data @@ -413,5 +385,5 @@ pub fn sendto_xdp( flags: SendFlags, addr: &SocketAddrXdp, ) -> io::Result { - backend::net::syscalls::sendto_xdp(fd.as_fd(), buf, flags, addr) + backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } diff --git a/src/net/send_recv/msg.rs b/src/net/send_recv/msg.rs index 56b0100ac..d21a9646b 100644 --- a/src/net/send_recv/msg.rs +++ b/src/net/send_recv/msg.rs @@ -5,6 +5,7 @@ use crate::backend::{self, c}; use crate::fd::{AsFd, BorrowedFd, OwnedFd}; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::addr::SocketAddrArg; #[cfg(linux_kernel)] use crate::net::UCred; #[cfg(feature = "std")] @@ -627,6 +628,37 @@ pub fn sendmsg( backend::net::syscalls::sendmsg(socket.as_fd(), 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_addr( + socket: impl AsFd, + addr: &impl SocketAddrArg, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) +} + /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv4 address. /// /// # References @@ -655,7 +687,7 @@ pub fn sendmsg_v4( control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result { - backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags) + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) } /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv6 address. @@ -686,7 +718,7 @@ pub fn sendmsg_v6( control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result { - backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags) + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) } /// `sendmsg(msghdr)`—Sends a message on a socket to a specific Unix-domain @@ -719,7 +751,7 @@ pub fn sendmsg_unix( control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result { - backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags) + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) } /// `sendmsg(msghdr)`—Sends a message on a socket to a specific XDP address. @@ -737,7 +769,7 @@ pub fn sendmsg_xdp( control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result { - backend::net::syscalls::sendmsg_xdp(socket.as_fd(), addr, iov, control, flags) + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) } /// `sendmsg(msghdr)`—Sends a message on a socket to a specific address. @@ -770,19 +802,8 @@ pub fn sendmsg_any( ) -> io::Result { 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) - } - #[cfg(target_os = "linux")] - Some(SocketAddrAny::Xdp(addr)) => { - backend::net::syscalls::sendmsg_xdp(socket.as_fd(), addr, iov, control, flags) + Some(addr) => { + backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) } } } diff --git a/src/net/socket.rs b/src/net/socket.rs index a3f943732..6314ef223 100644 --- a/src/net/socket.rs +++ b/src/net/socket.rs @@ -1,7 +1,7 @@ use crate::fd::OwnedFd; -use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::net::{addr::SocketAddrArg, SocketAddrAny, SocketAddrV4, SocketAddrV6}; use crate::{backend, io}; -use backend::fd::{AsFd, BorrowedFd}; +use backend::fd::AsFd; #[cfg(target_os = "linux")] use crate::net::xdp::SocketAddrXdp; @@ -122,15 +122,8 @@ pub fn socket_with( /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=bind§ion=2 /// [illumos]: https://illumos.org/man/3SOCKET/bind /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html -pub fn bind(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), - } +pub fn bind(sockfd: Fd, addr: &impl SocketAddrArg) -> io::Result<()> { + backend::net::syscalls::bind(sockfd.as_fd(), addr) } /// `bind(sockfd, addr)`—Binds a socket to an address. @@ -161,18 +154,7 @@ fn _bind(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> { /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html #[doc(alias = "bind")] pub fn bind_any(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), - #[cfg(target_os = "linux")] - SocketAddrAny::Xdp(xdp) => backend::net::syscalls::bind_xdp(sockfd, xdp), - } + backend::net::syscalls::bind(sockfd.as_fd(), addr) } /// `bind(sockfd, addr, sizeof(struct sockaddr_in))`—Binds a socket to an @@ -205,7 +187,7 @@ fn _bind_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> { #[inline] #[doc(alias = "bind")] pub fn bind_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { - backend::net::syscalls::bind_v4(sockfd.as_fd(), addr) + backend::net::syscalls::bind(sockfd.as_fd(), addr) } /// `bind(sockfd, addr, sizeof(struct sockaddr_in6))`—Binds a socket to an @@ -238,7 +220,7 @@ pub fn bind_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { #[inline] #[doc(alias = "bind")] pub fn bind_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { - backend::net::syscalls::bind_v6(sockfd.as_fd(), addr) + backend::net::syscalls::bind(sockfd.as_fd(), addr) } /// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a @@ -272,11 +254,10 @@ pub fn bind_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { #[inline] #[doc(alias = "bind")] pub fn bind_unix(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { - backend::net::syscalls::bind_unix(sockfd.as_fd(), addr) + backend::net::syscalls::bind(sockfd.as_fd(), addr) } -/// `bind(sockfd, addr, sizeof(struct sockaddr_un))`—Binds a socket to a XDP -/// address. +/// `bind(sockfd, addr, sizeof(struct sockaddr_xdp))`—Binds a socket to a XDP address. /// /// # References /// - [Linux] @@ -286,7 +267,7 @@ pub fn bind_unix(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> #[inline] #[doc(alias = "bind")] pub fn bind_xdp(sockfd: Fd, addr: &SocketAddrXdp) -> io::Result<()> { - backend::net::syscalls::bind_xdp(sockfd.as_fd(), addr) + backend::net::syscalls::bind(sockfd.as_fd(), addr) } /// `connect(sockfd, addr)`—Initiates a connection to an IP address. @@ -320,15 +301,8 @@ pub fn bind_xdp(sockfd: Fd, addr: &SocketAddrXdp) -> io::Result<()> { /// [illumos]: https://illumos.org/man/3SOCKET/connect /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Connecting.html /// [`Errno::WOULDBLOCK`]: io::Errno::WOULDBLOCK -pub fn connect(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), - } +pub fn connect(sockfd: Fd, addr: &impl SocketAddrArg) -> io::Result<()> { + backend::net::syscalls::connect(sockfd.as_fd(), addr) } /// `connect(sockfd, addr)`—Initiates a connection. @@ -359,18 +333,7 @@ fn _connect(sockfd: BorrowedFd<'_>, addr: &SocketAddr) -> io::Result<()> { /// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/Connecting.html #[doc(alias = "connect")] pub fn connect_any(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), - #[cfg(target_os = "linux")] - SocketAddrAny::Xdp(_) => Err(io::Errno::OPNOTSUPP), - } + backend::net::syscalls::connect(sockfd.as_fd(), addr) } /// `connect(sockfd, addr, sizeof(struct sockaddr_in))`—Initiates a @@ -403,7 +366,7 @@ fn _connect_any(sockfd: BorrowedFd<'_>, addr: &SocketAddrAny) -> io::Result<()> #[inline] #[doc(alias = "connect")] pub fn connect_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { - backend::net::syscalls::connect_v4(sockfd.as_fd(), addr) + backend::net::syscalls::connect(sockfd.as_fd(), addr) } /// `connect(sockfd, addr, sizeof(struct sockaddr_in6))`—Initiates a @@ -436,7 +399,7 @@ pub fn connect_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { #[inline] #[doc(alias = "connect")] pub fn connect_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { - backend::net::syscalls::connect_v6(sockfd.as_fd(), addr) + backend::net::syscalls::connect(sockfd.as_fd(), addr) } /// `connect(sockfd, addr, sizeof(struct sockaddr_un))`—Initiates a @@ -470,7 +433,7 @@ pub fn connect_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { #[inline] #[doc(alias = "connect")] pub fn connect_unix(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { - backend::net::syscalls::connect_unix(sockfd.as_fd(), addr) + backend::net::syscalls::connect(sockfd.as_fd(), addr) } /// `connect(sockfd, {.sa_family = AF_UNSPEC}, sizeof(struct sockaddr))`— diff --git a/src/net/socket_addr_any.rs b/src/net/socket_addr_any.rs index 2a99ebac4..726943c77 100644 --- a/src/net/socket_addr_any.rs +++ b/src/net/socket_addr_any.rs @@ -13,10 +13,14 @@ use crate::net::xdp::SocketAddrXdp; #[cfg(unix)] use crate::net::SocketAddrUnix; -use crate::net::{AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::net::{ + addr::{SocketAddrArg, SocketAddrOpaque}, + AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6, +}; use crate::{backend, io}; #[cfg(feature = "std")] use core::fmt; +use core::ptr::copy_nonoverlapping; pub use backend::net::addr::SocketAddrStorage; @@ -92,7 +96,10 @@ impl SocketAddrAny { /// `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) + self.with_sockaddr(|addr, len| { + copy_nonoverlapping(addr.cast::(), storage.cast::(), len as usize); + len as usize + }) } /// Reads a platform-specific encoding of a socket address from @@ -120,3 +127,16 @@ impl fmt::Debug for SocketAddrAny { } } } + +unsafe impl SocketAddrArg for SocketAddrAny { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + match self { + Self::V4(a) => a.with_sockaddr(f), + Self::V6(a) => a.with_sockaddr(f), + #[cfg(unix)] + Self::Unix(a) => a.with_sockaddr(f), + #[cfg(target_os = "linux")] + Self::Xdp(a) => a.with_sockaddr(f), + } + } +} diff --git a/src/net/types.rs b/src/net/types.rs index fc16219aa..9bedb50f5 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -1539,6 +1539,8 @@ bitflags! { /// `AF_XDP` related types and constants. #[cfg(target_os = "linux")] pub mod xdp { + use crate::net::addr::{call_with_sockaddr, SocketAddrArg, SocketAddrOpaque}; + use super::{bitflags, c}; bitflags! { @@ -1678,6 +1680,21 @@ pub mod xdp { } } + #[allow(unsafe_code)] + unsafe impl SocketAddrArg for SocketAddrXdp { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + let addr = c::sockaddr_xdp { + sxdp_family: c::AF_XDP as _, + sxdp_flags: self.flags().bits(), + sxdp_ifindex: self.interface_index(), + sxdp_queue_id: self.queue_id(), + sxdp_shared_umem_fd: self.shared_umem_fd(), + }; + + call_with_sockaddr(&addr, f) + } + } + /// XDP ring offset. /// /// Used to mmap rings from kernel. From 2c1da03935b9a15523c67a618f4a4464cd5ac46d Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Thu, 30 Jan 2025 23:21:14 -0700 Subject: [PATCH 2/5] Move `SocketAddrStorage` to `crate::net::addr` --- src/backend/libc/net/sockopt.rs | 4 ++-- src/backend/linux_raw/net/sockopt.rs | 4 ++-- src/net/addr.rs | 2 ++ src/net/mod.rs | 2 +- src/net/socket_addr_any.rs | 4 +--- src/net/types.rs | 2 +- tests/net/addr.rs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/backend/libc/net/sockopt.rs b/src/backend/libc/net/sockopt.rs index 923ca241c..042329944 100644 --- a/src/backend/libc/net/sockopt.rs +++ b/src/backend/libc/net/sockopt.rs @@ -47,9 +47,9 @@ use crate::net::Protocol; target_env = "newlib" ))] use crate::net::RawProtocol; -use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; #[cfg(any(linux_kernel, target_os = "fuchsia"))] -use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrV4}; +use crate::net::{addr::SocketAddrStorage, SocketAddrAny, SocketAddrV4}; +use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; #[cfg(linux_kernel)] use crate::net::{SocketAddrV6, UCred}; use crate::utils::as_mut_ptr; diff --git a/src/backend/linux_raw/net/sockopt.rs b/src/backend/linux_raw/net/sockopt.rs index 8903e4b8a..e2fabbe3c 100644 --- a/src/backend/linux_raw/net/sockopt.rs +++ b/src/backend/linux_raw/net/sockopt.rs @@ -15,8 +15,8 @@ use crate::net::sockopt::Timeout; #[cfg(target_os = "linux")] use crate::net::xdp::{XdpMmapOffsets, XdpOptionsFlags, XdpRingOffset, XdpStatistics, XdpUmemReg}; use crate::net::{ - AddressFamily, Ipv4Addr, Ipv6Addr, Protocol, RawProtocol, SocketAddrAny, SocketAddrStorage, - SocketAddrV4, SocketAddrV6, SocketType, UCred, + addr::SocketAddrStorage, AddressFamily, Ipv4Addr, Ipv6Addr, Protocol, RawProtocol, + SocketAddrAny, SocketAddrV4, SocketAddrV6, SocketType, UCred, }; #[cfg(feature = "alloc")] use alloc::borrow::ToOwned; diff --git a/src/net/addr.rs b/src/net/addr.rs index 36b3fe6aa..b5f1e833f 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -10,6 +10,8 @@ use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6 use super::{SocketAddr, SocketAddrV4, SocketAddrV6}; +pub use crate::backend::net::addr::SocketAddrStorage; + #[cfg(unix)] use super::SocketAddrUnix; diff --git a/src/net/mod.rs b/src/net/mod.rs index 05d62bd6d..cb6459b56 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -26,7 +26,7 @@ pub use crate::maybe_polyfill::net::{ }; pub use send_recv::*; pub use socket::*; -pub use socket_addr_any::{SocketAddrAny, SocketAddrStorage}; +pub use socket_addr_any::SocketAddrAny; #[cfg(not(any(windows, target_os = "wasi")))] pub use socketpair::socketpair; pub use types::*; diff --git a/src/net/socket_addr_any.rs b/src/net/socket_addr_any.rs index 726943c77..fe5e8133f 100644 --- a/src/net/socket_addr_any.rs +++ b/src/net/socket_addr_any.rs @@ -14,7 +14,7 @@ use crate::net::xdp::SocketAddrXdp; #[cfg(unix)] use crate::net::SocketAddrUnix; use crate::net::{ - addr::{SocketAddrArg, SocketAddrOpaque}, + addr::{SocketAddrArg, SocketAddrOpaque, SocketAddrStorage}, AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6, }; use crate::{backend, io}; @@ -22,8 +22,6 @@ use crate::{backend, io}; use core::fmt; use core::ptr::copy_nonoverlapping; -pub use backend::net::addr::SocketAddrStorage; - /// `struct sockaddr_storage` as a Rust enum. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[doc(alias = "sockaddr")] diff --git a/src/net/types.rs b/src/net/types.rs index 9bedb50f5..e401098a3 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -1864,7 +1864,7 @@ fn test_sizes() { #[cfg(target_os = "linux")] use crate::backend::c; use crate::ffi::c_int; - use crate::net::SocketAddrStorage; + use crate::net::addr::SocketAddrStorage; use core::mem::transmute; // Backend code needs to cast these to `c_int` so make sure that cast isn't diff --git a/tests/net/addr.rs b/tests/net/addr.rs index 81b86d74b..d3f2aaf6b 100644 --- a/tests/net/addr.rs +++ b/tests/net/addr.rs @@ -3,7 +3,7 @@ fn encode_decode() { #[cfg(unix)] use rustix::net::SocketAddrUnix; use rustix::net::{ - Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrStorage, SocketAddrV4, SocketAddrV6, + addr::SocketAddrStorage, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6, }; unsafe { From 4daf7704c482ac206d58f8004abe334c1eece887 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 1 Feb 2025 13:28:13 -0700 Subject: [PATCH 3/5] Replace SocketAddrAny enum with a safe wrapper for SocketAddrStorage To support extensibility over address types, use sockaddr_storage and Into / TryInto conversions. --- src/backend/libc/net/addr.rs | 1 + src/backend/libc/net/msghdr.rs | 12 +- src/backend/libc/net/read_sockaddr.rs | 335 +++++++------------- src/backend/libc/net/sockopt.rs | 26 +- src/backend/libc/net/syscalls.rs | 94 +++--- src/backend/linux_raw/net/addr.rs | 1 + src/backend/linux_raw/net/msghdr.rs | 11 +- src/backend/linux_raw/net/read_sockaddr.rs | 235 +++++--------- src/backend/linux_raw/net/sockopt.rs | 27 +- src/backend/linux_raw/net/syscalls.rs | 142 ++++----- src/net/addr.rs | 16 +- src/net/mod.rs | 1 + src/net/socket_addr_any.rs | 338 +++++++++++++++------ src/net/types.rs | 21 +- tests/event/epoll.rs | 7 +- tests/net/addr.rs | 37 +-- tests/net/connect_bind_send.rs | 70 ++--- tests/net/dgram.rs | 137 ++------- tests/net/poll.rs | 8 +- tests/net/unix.rs | 10 +- tests/net/unix_alloc.rs | 5 +- tests/net/v4.rs | 14 +- tests/net/v6.rs | 14 +- 23 files changed, 660 insertions(+), 902 deletions(-) diff --git a/src/backend/libc/net/addr.rs b/src/backend/libc/net/addr.rs index 00a4c57aa..eefd056d8 100644 --- a/src/backend/libc/net/addr.rs +++ b/src/backend/libc/net/addr.rs @@ -238,6 +238,7 @@ impl fmt::Debug for SocketAddrUnix { /// `struct sockaddr_storage`. #[repr(transparent)] +#[derive(Copy, Clone)] pub struct SocketAddrStorage(c::sockaddr_storage); impl SocketAddrStorage { diff --git a/src/backend/libc/net/msghdr.rs b/src/backend/libc/net/msghdr.rs index 231129c14..f979d04b6 100644 --- a/src/backend/libc/net/msghdr.rs +++ b/src/backend/libc/net/msghdr.rs @@ -7,24 +7,24 @@ use crate::backend::c; use crate::backend::conv::{msg_control_len, msg_iov_len}; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::SocketAddrBuf; use crate::net::{addr::SocketAddrArg, RecvAncillaryBuffer, SendAncillaryBuffer}; -use core::mem::{size_of, zeroed, MaybeUninit}; +use core::mem::zeroed; /// Create a message header intended to receive a datagram. pub(crate) fn with_recv_msghdr( - name: &mut MaybeUninit, + name: &mut SocketAddrBuf, iov: &mut [IoSliceMut<'_>], control: &mut RecvAncillaryBuffer<'_>, f: impl FnOnce(&mut c::msghdr) -> io::Result, ) -> io::Result { control.clear(); - let namelen = size_of::() as c::socklen_t; let mut msghdr = { let mut h = zero_msghdr(); - h.msg_name = name.as_mut_ptr().cast(); - h.msg_namelen = namelen; + h.msg_name = name.storage.as_mut_ptr().cast(); + h.msg_namelen = name.len; h.msg_iov = iov.as_mut_ptr().cast(); h.msg_iovlen = msg_iov_len(iov.len()); h.msg_control = control.as_control_ptr().cast(); @@ -41,6 +41,8 @@ pub(crate) fn with_recv_msghdr( } } + name.len = msghdr.msg_namelen; + res } diff --git a/src/backend/libc/net/read_sockaddr.rs b/src/backend/libc/net/read_sockaddr.rs index f011b40a4..61a7e196c 100644 --- a/src/backend/libc/net/read_sockaddr.rs +++ b/src/backend/libc/net/read_sockaddr.rs @@ -7,15 +7,15 @@ use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id}; use crate::backend::c; #[cfg(not(windows))] use crate::ffi::CStr; -use crate::io; +use crate::io::Errno; #[cfg(target_os = "linux")] use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp}; -use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::net::{AddressFamily, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; use core::mem::size_of; // This must match the header of `sockaddr`. #[repr(C)] -struct sockaddr_header { +pub(crate) struct sockaddr_header { #[cfg(any( bsd, target_os = "aix", @@ -97,7 +97,7 @@ pub(crate) unsafe fn read_sa_family(storage: *const c::sockaddr) -> u16 { /// socket address. #[cfg(apple)] #[inline] -unsafe fn read_sun_path0(storage: *const c::sockaddr_storage) -> u8 { +unsafe fn read_sun_path0(storage: *const c::sockaddr) -> u8 { // In `read_ss_family` we assert that we know the layout of `sockaddr`. storage .cast::() @@ -105,252 +105,137 @@ unsafe fn read_sun_path0(storage: *const c::sockaddr_storage) -> u8 { .read() } -/// Set the `sa_family` field of a socket address to `AF_UNSPEC`, so that we -/// can test for `AF_UNSPEC` to test whether it was stored to. -pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) { - (*storage.cast::()).sa_family = c::AF_UNSPEC as _; -} - -/// Read a socket address encoded in a platform-specific format. -/// -/// # Safety -/// -/// `storage` must point to valid socket address storage. -pub(crate) unsafe fn read_sockaddr( - storage: *const c::sockaddr, - len: usize, -) -> io::Result { - #[cfg(unix)] - let offsetof_sun_path = super::addr::offsetof_sun_path(); - - if len < size_of::() { - return Err(io::Errno::INVAL); - } - match read_sa_family(storage).into() { - c::AF_INET => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - Ok(SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), - u16::from_be(decode.sin_port), - ))) - } - c::AF_INET6 => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - #[cfg(not(windows))] - let s6_addr = decode.sin6_addr.s6_addr; - #[cfg(windows)] - let s6_addr = decode.sin6_addr.u.Byte; - #[cfg(not(windows))] - let sin6_scope_id = decode.sin6_scope_id; - #[cfg(windows)] - let sin6_scope_id = decode.Anonymous.sin6_scope_id; - Ok(SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(s6_addr), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - sin6_scope_id, - ))) - } - #[cfg(unix)] - c::AF_UNIX => { - if len < offsetof_sun_path { - return Err(io::Errno::INVAL); - } - if len == offsetof_sun_path { - SocketAddrUnix::new(&[][..]).map(SocketAddrAny::Unix) - } else { - let decode = &*storage.cast::(); - - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - #[cfg(linux_kernel)] - if decode.sun_path[0] == 0 { - return SocketAddrUnix::new_abstract_name(core::mem::transmute::< - &[c::c_char], - &[u8], - >( - &decode.sun_path[1..len - offsetof_sun_path], - )) - .map(SocketAddrAny::Unix); - } - - // Otherwise we expect a NUL-terminated filesystem path. - - // Trim off unused bytes from the end of `path_bytes`. - let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) { - // FreeBSD and illumos sometimes set the length to longer - // than the length of the NUL-terminated string. Find the - // NUL and truncate the string accordingly. - &decode.sun_path[..decode - .sun_path - .iter() - .position(|b| *b == 0) - .ok_or(io::Errno::INVAL)?] - } else { - // Otherwise, use the provided length. - let provided_len = len - 1 - offsetof_sun_path; - if decode.sun_path[provided_len] != 0 { - return Err(io::Errno::INVAL); - } - debug_assert_eq!( - CStr::from_ptr(decode.sun_path.as_ptr().cast()) - .to_bytes() - .len(), - provided_len - ); - &decode.sun_path[..provided_len] - }; - - SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) - .map(SocketAddrAny::Unix) - } - } - #[cfg(target_os = "linux")] - c::AF_XDP => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - Ok(SocketAddrAny::Xdp(SocketAddrXdp::new( - SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), - u32::from_be(decode.sxdp_ifindex), - u32::from_be(decode.sxdp_queue_id), - u32::from_be(decode.sxdp_shared_umem_fd), - ))) - } - _ => Err(io::Errno::INVAL), - } -} - -/// Read an optional socket address returned from the OS. +/// Check if a socket address returned from the OS is considered non-empty. /// /// # Safety /// /// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn maybe_read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> Option { +#[inline] +pub(crate) unsafe fn sockaddr_nonempty(storage: *const c::sockaddr, len: usize) -> bool { if len == 0 { - return None; + return false; } assert!(len >= size_of::()); - let family = read_sa_family(storage.cast::()).into(); + let family: c::c_int = read_sa_family(storage.cast::()).into(); if family == c::AF_UNSPEC { - return None; + return false; } // On macOS, if we get an `AF_UNIX` with an empty path, treat it as // an absent address. #[cfg(apple)] if family == c::AF_UNIX && read_sun_path0(storage) == 0 { - return None; + return false; } - Some(inner_read_sockaddr_os(family, storage, len)) + true } -/// Read a socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> SocketAddrAny { - assert!(len >= size_of::()); - let family = read_sa_family(storage.cast::()).into(); - inner_read_sockaddr_os(family, storage, len) +/// Set the `sa_family` field of a socket address to `AF_UNSPEC`, so that we +/// can test for `AF_UNSPEC` to test whether it was stored to. +pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) { + (*storage.cast::()).sa_family = c::AF_UNSPEC as _; } -unsafe fn inner_read_sockaddr_os( - family: c::c_int, - storage: *const c::sockaddr_storage, - len: usize, -) -> SocketAddrAny { - #[cfg(unix)] - let offsetof_sun_path = super::addr::offsetof_sun_path(); - - assert!(len >= size_of::()); - match family { - c::AF_INET => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), - u16::from_be(decode.sin_port), - )) - } - c::AF_INET6 => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - sockaddr_in6_sin6_scope_id(decode), - )) - } - #[cfg(unix)] - c::AF_UNIX => { - assert!(len >= offsetof_sun_path); - if len == offsetof_sun_path { - SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()) - } else { - let decode = &*storage.cast::(); +#[inline] +pub(crate) fn read_sockaddr_v4(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::INET { + return Err(Errno::AFNOSUPPORT); + } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrV4::new( + Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), + u16::from_be(decode.sin_port), + )) +} - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - #[cfg(linux_kernel)] - if decode.sun_path[0] == 0 { - return SocketAddrAny::Unix( - SocketAddrUnix::new_abstract_name(core::mem::transmute::< - &[c::c_char], - &[u8], - >( - &decode.sun_path[1..len - offsetof_sun_path], - )) - .unwrap(), - ); - } +#[inline] +pub(crate) fn read_sockaddr_v6(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::INET6 { + return Err(Errno::AFNOSUPPORT); + } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrV6::new( + Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)), + u16::from_be(decode.sin6_port), + u32::from_be(decode.sin6_flowinfo), + sockaddr_in6_sin6_scope_id(decode), + )) +} - // Otherwise we expect a NUL-terminated filesystem path. - assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); - let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; +#[cfg(unix)] +#[inline] +pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::UNIX { + return Err(Errno::AFNOSUPPORT); + } - // FreeBSD and illumos sometimes set the length to longer than - // the length of the NUL-terminated string. Find the NUL and - // truncate the string accordingly. - #[cfg(any(solarish, target_os = "freebsd"))] - let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()]; + let offsetof_sun_path = super::addr::offsetof_sun_path(); + let len = addr.len(); + + assert!(len >= offsetof_sun_path); + + if len == offsetof_sun_path { + SocketAddrUnix::new(&[][..]) + } else { + let decode = unsafe { &*addr.as_ptr().cast::() }; + + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + #[cfg(linux_kernel)] + if decode.sun_path[0] == 0 { + let name = &decode.sun_path[1..len - offsetof_sun_path]; + let name = unsafe { core::mem::transmute::<&[c::c_char], &[u8]>(name) }; + return SocketAddrUnix::new_abstract_name(name); + } - SocketAddrAny::Unix( - SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) - .unwrap(), - ) + // Otherwise we expect a NUL-terminated filesystem path. + + // Trim off unused bytes from the end of `path_bytes`. + let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) { + // FreeBSD and illumos sometimes set the length to longer + // than the length of the NUL-terminated string. Find the + // NUL and truncate the string accordingly. + &decode.sun_path[..decode + .sun_path + .iter() + .position(|b| *b == 0) + .ok_or(Errno::INVAL)?] + } else { + // Otherwise, use the provided length. + let provided_len = len - 1 - offsetof_sun_path; + if decode.sun_path[provided_len] != 0 { + return Err(Errno::INVAL); } - } - #[cfg(target_os = "linux")] - c::AF_XDP => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::Xdp(SocketAddrXdp::new( - SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), - u32::from_be(decode.sxdp_ifindex), - u32::from_be(decode.sxdp_queue_id), - u32::from_be(decode.sxdp_shared_umem_fd), - )) - } - other => unimplemented!("{:?}", other), + debug_assert_eq!( + unsafe { CStr::from_ptr(decode.sun_path.as_ptr().cast()) } + .to_bytes() + .len(), + provided_len + ); + &decode.sun_path[..provided_len] + }; + + SocketAddrUnix::new(unsafe { core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes) }) + } +} + +#[cfg(target_os = "linux")] +#[inline] +pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::XDP { + return Err(Errno::AFNOSUPPORT); } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrXdp::new( + SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), + u32::from_be(decode.sxdp_ifindex), + u32::from_be(decode.sxdp_queue_id), + u32::from_be(decode.sxdp_shared_umem_fd), + )) } diff --git a/src/backend/libc/net/sockopt.rs b/src/backend/libc/net/sockopt.rs index 042329944..fef4709ce 100644 --- a/src/backend/libc/net/sockopt.rs +++ b/src/backend/libc/net/sockopt.rs @@ -48,7 +48,7 @@ use crate::net::Protocol; ))] use crate::net::RawProtocol; #[cfg(any(linux_kernel, target_os = "fuchsia"))] -use crate::net::{addr::SocketAddrStorage, SocketAddrAny, SocketAddrV4}; +use crate::net::SocketAddrV4; use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; #[cfg(linux_kernel)] use crate::net::{SocketAddrV6, UCred}; @@ -810,16 +810,10 @@ pub(crate) fn ipv6_freebind(fd: BorrowedFd<'_>) -> io::Result { pub(crate) fn ip_original_dst(fd: BorrowedFd<'_>) -> io::Result { let level = c::IPPROTO_IP; let optname = c::SO_ORIGINAL_DST; - let mut value = MaybeUninit::::uninit(); - let mut optlen = core::mem::size_of_val(&value).try_into().unwrap(); - getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?; - - let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? }; - match any { - SocketAddrAny::V4(v4) => Ok(v4), - _ => unreachable!(), - } + let mut addr = crate::net::SocketAddrBuf::new(); + getsockopt_raw(fd, level, optname, &mut addr.storage, &mut addr.len)?; + Ok(unsafe { addr.into_any() }.try_into().unwrap()) } #[cfg(linux_kernel)] @@ -827,16 +821,10 @@ pub(crate) fn ip_original_dst(fd: BorrowedFd<'_>) -> io::Result { pub(crate) fn ipv6_original_dst(fd: BorrowedFd<'_>) -> io::Result { let level = c::IPPROTO_IPV6; let optname = c::IP6T_SO_ORIGINAL_DST; - let mut value = MaybeUninit::::uninit(); - let mut optlen = core::mem::size_of_val(&value).try_into().unwrap(); - getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?; - - let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? }; - match any { - SocketAddrAny::V6(v6) => Ok(v6), - _ => unreachable!(), - } + let mut addr = crate::net::SocketAddrBuf::new(); + getsockopt_raw(fd, level, optname, &mut addr.storage, &mut addr.len)?; + Ok(unsafe { addr.into_any() }.try_into().unwrap()) } #[cfg(not(any( diff --git a/src/backend/libc/net/syscalls.rs b/src/backend/libc/net/syscalls.rs index 438fadb53..7df5fa90b 100644 --- a/src/backend/libc/net/syscalls.rs +++ b/src/backend/libc/net/syscalls.rs @@ -1,11 +1,12 @@ //! libc syscalls supporting `rustix::net`. -use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; +use super::read_sockaddr::initialize_family_to_unspec; use super::send_recv::{RecvFlags, SendFlags}; use crate::backend::c; use crate::backend::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; +use crate::net::SocketAddrBuf; use crate::net::{ addr::SocketAddrArg, AddressFamily, Protocol, Shutdown, SocketAddrAny, SocketFlags, SocketType, }; @@ -51,28 +52,23 @@ pub(crate) unsafe fn recvfrom( buf_len: usize, flags: RecvFlags, ) -> io::Result<(usize, Option)> { - let mut storage = MaybeUninit::::uninit(); - let mut len = size_of::() as c::socklen_t; + let mut addr = SocketAddrBuf::new(); // `recvfrom` does not write to the storage if the socket is // connection-oriented sockets, so we initialize the family field to // `AF_UNSPEC` so that we can detect this case. - initialize_family_to_unspec(storage.as_mut_ptr().cast::()); + initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::()); - ret_send_recv(c::recvfrom( + let nread = ret_send_recv(c::recvfrom( borrowed_fd(fd), buf.cast(), send_recv_len(buf_len), bitflags_bits!(flags), - storage.as_mut_ptr().cast::(), - &mut len, - )) - .map(|nread| { - ( - nread, - maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()), - ) - }) + addr.storage.as_mut_ptr().cast::(), + &mut addr.len, + ))?; + + Ok((nread, addr.into_any_option())) } pub(crate) fn sendto( @@ -186,28 +182,23 @@ pub(crate) fn recvmsg( control: &mut RecvAncillaryBuffer<'_>, msg_flags: RecvFlags, ) -> io::Result { - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); - with_recv_msghdr(&mut storage, iov, control, |msghdr| { - let result = unsafe { + let (bytes, flags) = with_recv_msghdr(&mut addr, iov, control, |msghdr| { + let bytes = unsafe { ret_send_recv(c::recvmsg( borrowed_fd(sockfd), msghdr, bitflags_bits!(msg_flags), - )) + ))? }; + Ok((bytes, msghdr.msg_flags)) + })?; - result.map(|bytes| { - // Get the address of the sender, if any. - let addr = - unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) }; - - RecvMsg { - bytes, - address: addr, - flags: ReturnFlags::from_bits_retain(bitcast!(msghdr.msg_flags)), - } - }) + Ok(RecvMsg { + bytes, + address: unsafe { addr.into_any_option() }, + flags: ReturnFlags::from_bits_retain(bitcast!(flags)), }) } @@ -268,17 +259,13 @@ pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: SocketFlags) -> io::Res pub(crate) fn acceptfrom(sockfd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option)> { unsafe { - let mut storage = MaybeUninit::::uninit(); - let mut len = size_of::() as c::socklen_t; + let mut addr = SocketAddrBuf::new(); let owned_fd = ret_owned_fd(c::accept( borrowed_fd(sockfd), - storage.as_mut_ptr().cast::(), - &mut len, + addr.storage.as_mut_ptr().cast::(), + &mut addr.len, ))?; - Ok(( - owned_fd, - maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()), - )) + Ok((owned_fd, addr.into_any_option())) } } @@ -297,18 +284,14 @@ pub(crate) fn acceptfrom_with( flags: SocketFlags, ) -> io::Result<(OwnedFd, Option)> { unsafe { - let mut storage = MaybeUninit::::uninit(); - let mut len = size_of::() as c::socklen_t; + let mut addr = SocketAddrBuf::new(); let owned_fd = ret_owned_fd(c::accept4( borrowed_fd(sockfd), - storage.as_mut_ptr().cast::(), - &mut len, + addr.storage.as_mut_ptr().cast::(), + &mut addr.len, flags.bits() as c::c_int, ))?; - Ok(( - owned_fd, - maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()), - )) + Ok((owned_fd, addr.into_any_option())) } } @@ -353,30 +336,25 @@ pub(crate) fn shutdown(sockfd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> pub(crate) fn getsockname(sockfd: BorrowedFd<'_>) -> io::Result { unsafe { - let mut storage = MaybeUninit::::uninit(); - let mut len = size_of::() as c::socklen_t; + let mut addr = SocketAddrBuf::new(); ret(c::getsockname( borrowed_fd(sockfd), - storage.as_mut_ptr().cast::(), - &mut len, + addr.storage.as_mut_ptr().cast::(), + &mut addr.len, ))?; - Ok(read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap())) + Ok(addr.into_any()) } } pub(crate) fn getpeername(sockfd: BorrowedFd<'_>) -> io::Result> { unsafe { - let mut storage = MaybeUninit::::uninit(); - let mut len = size_of::() as c::socklen_t; + let mut addr = SocketAddrBuf::new(); ret(c::getpeername( borrowed_fd(sockfd), - storage.as_mut_ptr().cast::(), - &mut len, + addr.storage.as_mut_ptr().cast::(), + &mut addr.len, ))?; - Ok(maybe_read_sockaddr_os( - storage.as_ptr(), - len.try_into().unwrap(), - )) + Ok(addr.into_any_option()) } } diff --git a/src/backend/linux_raw/net/addr.rs b/src/backend/linux_raw/net/addr.rs index 2ff384fb7..d03082dc8 100644 --- a/src/backend/linux_raw/net/addr.rs +++ b/src/backend/linux_raw/net/addr.rs @@ -192,6 +192,7 @@ impl fmt::Debug for SocketAddrUnix { /// `struct sockaddr_storage`. #[repr(transparent)] +#[derive(Copy, Clone)] pub struct SocketAddrStorage(c::sockaddr_storage); impl SocketAddrStorage { diff --git a/src/backend/linux_raw/net/msghdr.rs b/src/backend/linux_raw/net/msghdr.rs index 8734fd5f9..07f9e85ff 100644 --- a/src/backend/linux_raw/net/msghdr.rs +++ b/src/backend/linux_raw/net/msghdr.rs @@ -8,9 +8,9 @@ use crate::backend::c; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::SocketAddrBuf; use crate::net::{addr::SocketAddrArg, RecvAncillaryBuffer, SendAncillaryBuffer}; -use core::mem::{size_of, MaybeUninit}; use core::ptr::null_mut; fn msg_iov_len(len: usize) -> c::size_t { @@ -25,17 +25,16 @@ pub(crate) fn msg_control_len(len: usize) -> c::size_t { /// Create a message header intended to receive a datagram. pub(crate) fn with_recv_msghdr( - name: &mut MaybeUninit, + name: &mut SocketAddrBuf, iov: &mut [IoSliceMut<'_>], control: &mut RecvAncillaryBuffer<'_>, f: impl FnOnce(&mut c::msghdr) -> io::Result, ) -> io::Result { control.clear(); - let namelen = size_of::() as c::c_int; let mut msghdr = c::msghdr { - msg_name: name.as_mut_ptr().cast(), - msg_namelen: namelen, + msg_name: name.storage.as_mut_ptr().cast(), + msg_namelen: name.len as _, msg_iov: iov.as_mut_ptr().cast(), msg_iovlen: msg_iov_len(iov.len()), msg_control: control.as_control_ptr().cast(), @@ -52,6 +51,8 @@ pub(crate) fn with_recv_msghdr( } } + name.len = msghdr.msg_namelen as _; + res } diff --git a/src/backend/linux_raw/net/read_sockaddr.rs b/src/backend/linux_raw/net/read_sockaddr.rs index 03318ea07..367475d93 100644 --- a/src/backend/linux_raw/net/read_sockaddr.rs +++ b/src/backend/linux_raw/net/read_sockaddr.rs @@ -3,16 +3,17 @@ #![allow(unsafe_code)] use crate::backend::c; -use crate::io; +use crate::io::Errno; #[cfg(target_os = "linux")] use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp}; -use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; +use crate::net::{AddressFamily, SocketAddrAny}; +use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; use core::mem::size_of; use core::slice; // This must match the header of `sockaddr`. #[repr(C)] -struct sockaddr_header { +pub(crate) struct sockaddr_header { sa_family: u16, } @@ -22,7 +23,7 @@ struct sockaddr_header { /// /// `storage` must point to a valid socket address returned from the OS. #[inline] -pub(crate) unsafe fn read_sa_family(storage: *const c::sockaddr) -> u16 { +pub(crate) const unsafe fn read_sa_family(storage: *const c::sockaddr) -> u16 { // Assert that we know the layout of `sockaddr`. let _ = c::sockaddr { __storage: c::sockaddr_storage { @@ -46,179 +47,89 @@ pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) { (*storage.cast::()).sa_family = c::AF_UNSPEC as _; } -/// Read a socket address encoded in a platform-specific format. -/// -/// # Safety -/// -/// `storage` must point to valid socket address storage. -pub(crate) unsafe fn read_sockaddr( - storage: *const c::sockaddr, - len: usize, -) -> io::Result { - let offsetof_sun_path = super::addr::offsetof_sun_path(); +/// Check if a socket address returned from the OS is considered non-empty. +#[inline] +pub(crate) unsafe fn sockaddr_nonempty(_storage: *const c::sockaddr, len: usize) -> bool { + len != 0 +} - if len < size_of::() { - return Err(io::Errno::INVAL); - } - match read_sa_family(storage).into() { - c::AF_INET => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - Ok(SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)), - u16::from_be(decode.sin_port), - ))) - } - c::AF_INET6 => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - Ok(SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - decode.sin6_scope_id, - ))) - } - c::AF_UNIX => { - if len < offsetof_sun_path { - return Err(io::Errno::INVAL); - } - if len == offsetof_sun_path { - Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..])?)) - } else { - let decode = &*storage.cast::(); - - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - if decode.sun_path[0] == 0 { - let bytes = &decode.sun_path[1..len - offsetof_sun_path]; - - // SAFETY: Convert `&[c_char]` to `&[u8]`. - let bytes = slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()); - - return SocketAddrUnix::new_abstract_name(bytes).map(SocketAddrAny::Unix); - } - - // Otherwise we expect a NUL-terminated filesystem path. - let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; - - // SAFETY: Convert `&[c_char]` to `&[u8]`. - let bytes = slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()); - - assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); - Ok(SocketAddrAny::Unix(SocketAddrUnix::new(bytes)?)) - } - } - #[cfg(target_os = "linux")] - c::AF_XDP => { - if len < size_of::() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::(); - Ok(SocketAddrAny::Xdp(SocketAddrXdp::new( - SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), - u32::from_be(decode.sxdp_ifindex), - u32::from_be(decode.sxdp_queue_id), - u32::from_be(decode.sxdp_shared_umem_fd), - ))) - } - _ => Err(io::Errno::NOTSUP), +#[inline] +pub(crate) fn read_sockaddr_v4(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::INET { + return Err(Errno::AFNOSUPPORT); } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrV4::new( + Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)), + u16::from_be(decode.sin_port), + )) } -/// Read an optional socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn maybe_read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> Option { - if len == 0 { - None - } else { - Some(read_sockaddr_os(storage, len)) +#[inline] +pub(crate) fn read_sockaddr_v6(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::INET6 { + return Err(Errno::AFNOSUPPORT); } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrV6::new( + Ipv6Addr::from(unsafe { decode.sin6_addr.in6_u.u6_addr8 }), + u16::from_be(decode.sin6_port), + u32::from_be(decode.sin6_flowinfo), + decode.sin6_scope_id, + )) } -/// Read a socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> SocketAddrAny { +#[inline] +pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::UNIX { + return Err(Errno::AFNOSUPPORT); + } let offsetof_sun_path = super::addr::offsetof_sun_path(); + let len = addr.len(); - assert!(len >= size_of::()); - match read_sa_family(storage.cast::()).into() { - c::AF_INET => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)), - u16::from_be(decode.sin_port), - )) - } - c::AF_INET6 => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - decode.sin6_scope_id, - )) - } - c::AF_UNIX => { - assert!(len >= offsetof_sun_path); - if len == offsetof_sun_path { - SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()) - } else { - let decode = &*storage.cast::(); + assert!(len >= offsetof_sun_path); - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - if decode.sun_path[0] == 0 { - let bytes = &decode.sun_path[1..len - offsetof_sun_path]; + if len == offsetof_sun_path { + SocketAddrUnix::new(&[][..]) + } else { + let decode = unsafe { &*addr.as_ptr().cast::() }; - // SAFETY: Convert `&[c_char]` to `&[u8]`. - let bytes = slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()); + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + if decode.sun_path[0] == 0 { + let bytes = &decode.sun_path[1..len - offsetof_sun_path]; - return SocketAddrAny::Unix(SocketAddrUnix::new_abstract_name(bytes).unwrap()); - } + // SAFETY: Convert `&[c_char]` to `&[u8]`. + let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()) }; - // Otherwise we expect a NUL-terminated filesystem path. - assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); + return SocketAddrUnix::new_abstract_name(bytes); + } - let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; + // Otherwise we expect a NUL-terminated filesystem path. + let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; - // SAFETY: Convert `&[c_char]` to `&[u8]`. - let bytes = slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()); + // SAFETY: Convert `&[c_char]` to `&[u8]`. + let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::(), bytes.len()) }; - SocketAddrAny::Unix(SocketAddrUnix::new(bytes).unwrap()) - } - } - #[cfg(target_os = "linux")] - c::AF_XDP => { - assert!(len >= size_of::()); - let decode = &*storage.cast::(); - SocketAddrAny::Xdp(SocketAddrXdp::new( - SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), - u32::from_be(decode.sxdp_ifindex), - u32::from_be(decode.sxdp_queue_id), - u32::from_be(decode.sxdp_shared_umem_fd), - )) - } - other => unimplemented!("{:?}", other), + assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); + SocketAddrUnix::new(bytes) + } +} + +#[inline] +pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result { + if addr.address_family() != AddressFamily::XDP { + return Err(Errno::AFNOSUPPORT); } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrXdp::new( + SockaddrXdpFlags::from_bits_retain(decode.sxdp_flags), + u32::from_be(decode.sxdp_ifindex), + u32::from_be(decode.sxdp_queue_id), + u32::from_be(decode.sxdp_shared_umem_fd), + )) } diff --git a/src/backend/linux_raw/net/sockopt.rs b/src/backend/linux_raw/net/sockopt.rs index e2fabbe3c..a3a8b62cc 100644 --- a/src/backend/linux_raw/net/sockopt.rs +++ b/src/backend/linux_raw/net/sockopt.rs @@ -14,9 +14,10 @@ use crate::io; use crate::net::sockopt::Timeout; #[cfg(target_os = "linux")] use crate::net::xdp::{XdpMmapOffsets, XdpOptionsFlags, XdpRingOffset, XdpStatistics, XdpUmemReg}; +use crate::net::SocketAddrBuf; use crate::net::{ - addr::SocketAddrStorage, AddressFamily, Ipv4Addr, Ipv6Addr, Protocol, RawProtocol, - SocketAddrAny, SocketAddrV4, SocketAddrV6, SocketType, UCred, + AddressFamily, Ipv4Addr, Ipv6Addr, Protocol, RawProtocol, SocketAddrV4, SocketAddrV6, + SocketType, UCred, }; #[cfg(feature = "alloc")] use alloc::borrow::ToOwned; @@ -682,32 +683,22 @@ pub(crate) fn ipv6_freebind(fd: BorrowedFd<'_>) -> io::Result { pub(crate) fn ip_original_dst(fd: BorrowedFd<'_>) -> io::Result { let level = c::IPPROTO_IP; let optname = c::SO_ORIGINAL_DST; - let mut value = MaybeUninit::::uninit(); - let mut optlen = core::mem::size_of_val(&value).try_into().unwrap(); + let mut addr = SocketAddrBuf::new(); - getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?; + getsockopt_raw(fd, level, optname, &mut addr.storage, &mut addr.len)?; - let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? }; - match any { - SocketAddrAny::V4(v4) => Ok(v4), - _ => unreachable!(), - } + Ok(unsafe { addr.into_any() }.try_into().unwrap()) } #[inline] pub(crate) fn ipv6_original_dst(fd: BorrowedFd<'_>) -> io::Result { let level = c::IPPROTO_IPV6; let optname = c::IP6T_SO_ORIGINAL_DST; - let mut value = MaybeUninit::::uninit(); - let mut optlen = core::mem::size_of_val(&value).try_into().unwrap(); + let mut addr = SocketAddrBuf::new(); - getsockopt_raw(fd, level, optname, &mut value, &mut optlen)?; + getsockopt_raw(fd, level, optname, &mut addr.storage, &mut addr.len)?; - let any = unsafe { SocketAddrAny::read(value.as_ptr(), optlen as usize)? }; - match any { - SocketAddrAny::V6(v6) => Ok(v6), - _ => unreachable!(), - } + Ok(unsafe { addr.into_any() }.try_into().unwrap()) } #[inline] diff --git a/src/backend/linux_raw/net/syscalls.rs b/src/backend/linux_raw/net/syscalls.rs index f239016ba..21822f54e 100644 --- a/src/backend/linux_raw/net/syscalls.rs +++ b/src/backend/linux_raw/net/syscalls.rs @@ -6,7 +6,7 @@ #![allow(unsafe_code, clippy::undocumented_unsafe_blocks)] use super::msghdr::{with_msghdr, with_noaddr_msghdr, with_recv_msghdr}; -use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; +use super::read_sockaddr::initialize_family_to_unspec; use super::send_recv::{RecvFlags, ReturnFlags, SendFlags}; use crate::backend::c; use crate::backend::conv::{ @@ -16,11 +16,12 @@ use crate::backend::conv::{ use crate::backend::reg::raw_arg; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::SocketAddrBuf; use crate::net::{ addr::SocketAddrArg, AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsg, SendAncillaryBuffer, Shutdown, SocketAddrAny, SocketFlags, SocketType, }; -use c::{sockaddr_storage, socklen_t}; +use c::socklen_t; use core::mem::MaybeUninit; #[cfg(target_arch = "x86")] use { @@ -170,36 +171,28 @@ pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result< pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option)> { #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); let fd = ret_owned_fd(syscall!( __NR_accept, fd, - &mut storage, - by_mut(&mut addrlen) + &mut addr.storage, + by_mut(&mut addr.len) ))?; - Ok(( - fd, - maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), - )) + Ok((fd, addr.into_any_option())) } #[cfg(target_arch = "x86")] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); let fd = ret_owned_fd(syscall!( __NR_socketcall, x86_sys(SYS_ACCEPT), slice_just_addr::, _>(&[ fd.into(), - (&mut storage).into(), - by_mut(&mut addrlen), + (&mut addr.storage).into(), + by_mut(&mut addr.len), ]) ))?; - Ok(( - fd, - maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), - )) + Ok((fd, addr.into_any_option())) } #[cfg(target_arch = "s390x")] { @@ -215,38 +208,30 @@ pub(crate) fn acceptfrom_with( ) -> io::Result<(OwnedFd, Option)> { #[cfg(not(target_arch = "x86"))] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); let fd = ret_owned_fd(syscall!( __NR_accept4, fd, - &mut storage, - by_mut(&mut addrlen), + &mut addr.storage, + by_mut(&mut addr.len), flags ))?; - Ok(( - fd, - maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), - )) + Ok((fd, addr.into_any_option())) } #[cfg(target_arch = "x86")] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); let fd = ret_owned_fd(syscall!( __NR_socketcall, x86_sys(SYS_ACCEPT4), slice_just_addr::, _>(&[ fd.into(), - (&mut storage).into(), - by_mut(&mut addrlen), + (&mut addr.storage).into(), + by_mut(&mut addr.len), flags.into(), ]) ))?; - Ok(( - fd, - maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), - )) + Ok((fd, addr.into_any_option())) } } @@ -257,9 +242,9 @@ pub(crate) fn recvmsg( control: &mut RecvAncillaryBuffer<'_>, msg_flags: RecvFlags, ) -> io::Result { - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); - with_recv_msghdr(&mut storage, iov, control, |msghdr| { + let (bytes, flags) = with_recv_msghdr(&mut addr, iov, control, |msghdr| { #[cfg(not(target_arch = "x86"))] let result = unsafe { ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags)) }; @@ -277,17 +262,14 @@ pub(crate) fn recvmsg( )) }; - result.map(|bytes| { - // Get the address of the sender, if any. - let addr = - unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) }; - - RecvMsg { - bytes, - address: addr, - flags: ReturnFlags::from_bits_retain(msghdr.msg_flags), - } - }) + result.map(|bytes| (bytes, msghdr.msg_flags)) + })?; + + // Get the address of the sender, if any. + Ok(RecvMsg { + bytes, + address: unsafe { addr.into_any_option() }, + flags: ReturnFlags::from_bits_retain(flags), }) } @@ -520,13 +502,12 @@ pub(crate) unsafe fn recvfrom( len: usize, flags: RecvFlags, ) -> io::Result<(usize, Option)> { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); // `recvfrom` does not write to the storage if the socket is // connection-oriented sockets, so we initialize the family field to // `AF_UNSPEC` so that we can detect this case. - initialize_family_to_unspec(storage.as_mut_ptr().cast::()); + initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::()); #[cfg(not(target_arch = "x86"))] let nread = ret_usize(syscall!( @@ -535,8 +516,8 @@ pub(crate) unsafe fn recvfrom( buf, pass_usize(len), flags, - &mut storage, - by_mut(&mut addrlen) + &mut addr.storage, + by_mut(&mut addr.len) ))?; #[cfg(target_arch = "x86")] let nread = ret_usize(syscall!( @@ -547,51 +528,40 @@ pub(crate) unsafe fn recvfrom( buf.into(), pass_usize(len), flags.into(), - (&mut storage).into(), - by_mut(&mut addrlen), + (&mut addr.storage).into(), + by_mut(&mut addr.len), ]) ))?; - Ok(( - nread, - maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), - )) + Ok((nread, addr.into_any_option())) } #[inline] pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result> { #[cfg(not(target_arch = "x86"))] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); ret(syscall!( __NR_getpeername, fd, - &mut storage, - by_mut(&mut addrlen) + &mut addr.storage, + by_mut(&mut addr.len) ))?; - Ok(maybe_read_sockaddr_os( - &storage.assume_init(), - addrlen.try_into().unwrap(), - )) + Ok(addr.into_any_option()) } #[cfg(target_arch = "x86")] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); ret(syscall!( __NR_socketcall, x86_sys(SYS_GETPEERNAME), slice_just_addr::, _>(&[ fd.into(), - (&mut storage).into(), - by_mut(&mut addrlen), + (&mut addr.storage).into(), + by_mut(&mut addr.len), ]) ))?; - Ok(maybe_read_sockaddr_os( - &storage.assume_init(), - addrlen.try_into().unwrap(), - )) + Ok(addr.into_any_option()) } } @@ -599,36 +569,28 @@ pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result) -> io::Result { #[cfg(not(target_arch = "x86"))] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); ret(syscall!( __NR_getsockname, fd, - &mut storage, - by_mut(&mut addrlen) + &mut addr.storage, + by_mut(&mut addr.len) ))?; - Ok(read_sockaddr_os( - &storage.assume_init(), - addrlen.try_into().unwrap(), - )) + Ok(addr.into_any()) } #[cfg(target_arch = "x86")] unsafe { - let mut addrlen = core::mem::size_of::() as socklen_t; - let mut storage = MaybeUninit::::uninit(); + let mut addr = SocketAddrBuf::new(); ret(syscall!( __NR_socketcall, x86_sys(SYS_GETSOCKNAME), slice_just_addr::, _>(&[ fd.into(), - (&mut storage).into(), - by_mut(&mut addrlen), + (&mut addr.storage).into(), + by_mut(&mut addr.len), ]) ))?; - Ok(read_sockaddr_os( - &storage.assume_init(), - addrlen.try_into().unwrap(), - )) + Ok(addr.into_any()) } } diff --git a/src/net/addr.rs b/src/net/addr.rs index b5f1e833f..1b8f0932e 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -4,11 +4,14 @@ //! The concrete address types and [`SocketAddrAny`] are in [the parent module][`super`]. #![allow(unsafe_code)] -use core::mem::size_of; +use core::{ + mem::{size_of, MaybeUninit}, + ptr, +}; use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; -use super::{SocketAddr, SocketAddrV4, SocketAddrV6}; +use super::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; pub use crate::backend::net::addr::SocketAddrStorage; @@ -42,6 +45,15 @@ pub unsafe trait SocketAddrArg { /// * Other socket types can construct their C-compatible struct on the /// stack and call the closure with a pointer to it. fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R; + + /// Convert to `SocketAddrAny`. + fn as_any(&self) -> SocketAddrAny { + self.with_sockaddr(|ptr, len| unsafe { + let mut storage = MaybeUninit::::uninit(); + ptr::copy_nonoverlapping(ptr.cast::(), storage.as_mut_ptr().cast::(), len); + SocketAddrAny::new(storage, len) + }) + } } /// Helper for implementing SocketAddrArg::with_sockaddr diff --git a/src/net/mod.rs b/src/net/mod.rs index cb6459b56..e55609053 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -27,6 +27,7 @@ pub use crate::maybe_polyfill::net::{ pub use send_recv::*; pub use socket::*; pub use socket_addr_any::SocketAddrAny; +pub(crate) use socket_addr_any::SocketAddrBuf; #[cfg(not(any(windows, target_os = "wasi")))] pub use socketpair::socketpair; pub use types::*; diff --git a/src/net/socket_addr_any.rs b/src/net/socket_addr_any.rs index fe5e8133f..5fe8be858 100644 --- a/src/net/socket_addr_any.rs +++ b/src/net/socket_addr_any.rs @@ -1,140 +1,290 @@ -//! 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(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; #[cfg(unix)] use crate::net::SocketAddrUnix; -use crate::net::{ - addr::{SocketAddrArg, SocketAddrOpaque, SocketAddrStorage}, - AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6, +use crate::{ + backend::{c, net::read_sockaddr}, + io::Errno, + net::{ + addr::{SocketAddrArg, SocketAddrOpaque, SocketAddrStorage}, + AddressFamily, SocketAddr, SocketAddrV4, SocketAddrV6, + }, }; -use crate::{backend, io}; #[cfg(feature = "std")] use core::fmt; -use core::ptr::copy_nonoverlapping; - -/// `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), - /// `struct sockaddr_xdp` - #[cfg(target_os = "linux")] - Xdp(SocketAddrXdp), +use core::{ + mem::{size_of, MaybeUninit}, + num::NonZeroUsize, +}; + +/// Temporary buffer for creating a `SocketAddrAny` from a +/// syscall that writes to a `sockaddr_t` and `socklen_t` +pub(crate) struct SocketAddrBuf { + pub(crate) len: c::socklen_t, + pub(crate) storage: MaybeUninit, } -impl From for SocketAddrAny { +impl SocketAddrBuf { #[inline] - fn from(from: SocketAddr) -> Self { - match from { - SocketAddr::V4(v4) => Self::V4(v4), - SocketAddr::V6(v6) => Self::V6(v6), + pub(crate) fn new() -> Self { + SocketAddrBuf { + len: size_of::().try_into().unwrap(), + storage: MaybeUninit::::uninit(), } } -} -impl From for SocketAddrAny { + /// Convert the buffer into [`SocketAddrAny`]. + /// + /// # Safety + /// A valid address must have been written into `self.storage` + /// and its length written into `self.len`. #[inline] - fn from(from: SocketAddrV4) -> Self { - Self::V4(from) + pub(crate) unsafe fn into_any(self) -> SocketAddrAny { + SocketAddrAny::new(self.storage, self.len.try_into().unwrap()) } -} -impl From for SocketAddrAny { + /// Convert the buffer into [`Option]. + /// + /// This returns `None` if `len` is zero or other platform-specific + /// conditions define the address as empty. + /// + /// # Safety + /// Either valid address must have been written into `self.storage` + /// and its length written into `self.len`, or `self.len` must + /// have been set to 0. #[inline] - fn from(from: SocketAddrV6) -> Self { - Self::V6(from) + pub(crate) unsafe fn into_any_option(self) -> Option { + let len = self.len.try_into().unwrap(); + if read_sockaddr::sockaddr_nonempty(self.storage.as_ptr().cast(), len) { + Some(SocketAddrAny::new(self.storage, len)) + } else { + None + } } } -#[cfg(unix)] -impl From for SocketAddrAny { - #[inline] - fn from(from: SocketAddrUnix) -> Self { - Self::Unix(from) - } +/// A type that can hold any kind of socket address, as a safe abstraction for +/// `sockaddr_storage`. +/// +/// Socket addresses can be converted to `SocketAddrAny` via the [`From`] and +/// [`Into`] traits. `SocketAddrAny` can be converted back to a specific socket +/// address type with [`TryFrom`] and [`TryInto`]. These implementations return +/// [`Errno::AFNOSUPPORT`] if the address family does not match the requested +/// type. +#[derive(Clone)] +#[doc(alias = "sockaddr_storage")] +pub struct SocketAddrAny { + // Invariants: + // * `len` is at least `size_of::()` + // * `len` is at most `size_of::()` + // * The first `len` bytes of `storage` are initialized. + pub(crate) len: NonZeroUsize, + pub(crate) storage: MaybeUninit, } impl SocketAddrAny { - /// Return the address family of this socket address. + /// Creates a socket address from `storage`, which is initialized for + /// `len` bytes. + /// + /// # Panics + /// + /// if `len` is smaller than the sockaddr header or larger than + /// `SocketAddrStorage`. + /// + /// # Safety + /// + /// * `storage` must contain a valid socket address. + /// * `len` bytes must be initialized. #[inline] - pub const fn address_family(&self) -> AddressFamily { - match self { - Self::V4(_) => AddressFamily::INET, - Self::V6(_) => AddressFamily::INET6, - #[cfg(unix)] - Self::Unix(_) => AddressFamily::UNIX, - #[cfg(target_os = "linux")] - Self::Xdp(_) => AddressFamily::XDP, + pub unsafe fn new(storage: MaybeUninit, len: usize) -> Self { + assert!(len >= core::mem::size_of::()); + assert!(len <= core::mem::size_of::()); + let len = NonZeroUsize::new_unchecked(len); + Self { storage, len } + } + + /// Gets the initialized part of the storage as bytes. + #[inline] + fn bytes(&self) -> &[u8] { + let len = self.len.get(); + unsafe { core::slice::from_raw_parts(self.storage.as_ptr().cast(), len) } + } + + /// Gets the address family of this socket address. + #[inline] + pub fn address_family(&self) -> AddressFamily { + unsafe { + AddressFamily::from_raw(crate::backend::net::read_sockaddr::read_sa_family( + self.storage.as_ptr().cast(), + )) } } - /// 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 { - self.with_sockaddr(|addr, len| { - copy_nonoverlapping(addr.cast::(), storage.cast::(), len as usize); - len as usize - }) + /// Returns a raw pointer to the sockaddr. + #[inline] + pub fn as_ptr(&self) -> *const SocketAddrStorage { + self.storage.as_ptr() } - /// 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 { - backend::net::read_sockaddr::read_sockaddr(storage.cast(), len) + /// Returns a raw mutable pointer to the sockaddr. + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut SocketAddrStorage { + self.storage.as_mut_ptr() + } + + /// Returns the length of the encoded sockaddr. + #[inline] + pub fn len(&self) -> usize { + self.len.get() + } +} + +impl PartialEq for SocketAddrAny { + fn eq(&self, other: &SocketAddrAny) -> bool { + self.bytes() == other.bytes() + } +} + +impl Eq for SocketAddrAny {} + +impl PartialOrd for SocketAddrAny { + fn partial_cmp(&self, other: &SocketAddrAny) -> Option { + self.bytes().partial_cmp(other.bytes()) + } +} + +impl Ord for SocketAddrAny { + fn cmp(&self, other: &SocketAddrAny) -> core::cmp::Ordering { + self.bytes().cmp(other.bytes()) + } +} + +impl core::hash::Hash for SocketAddrAny { + fn hash(&self, state: &mut H) { + self.bytes().hash(state) } } #[cfg(feature = "std")] impl fmt::Debug for SocketAddrAny { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::V4(v4) => v4.fmt(f), - Self::V6(v6) => v6.fmt(f), + match self.address_family() { + AddressFamily::INET => { + if let Ok(addr) = SocketAddrV4::try_from(self.clone()) { + return addr.fmt(f); + } + } + AddressFamily::INET6 => { + if let Ok(addr) = SocketAddrV6::try_from(self.clone()) { + return addr.fmt(f); + } + } #[cfg(unix)] - Self::Unix(unix) => unix.fmt(f), + AddressFamily::UNIX => { + if let Ok(addr) = SocketAddrUnix::try_from(self.clone()) { + return addr.fmt(f); + } + } #[cfg(target_os = "linux")] - Self::Xdp(xdp) => xdp.fmt(f), + AddressFamily::XDP => { + if let Ok(addr) = crate::net::xdp::SocketAddrXdp::try_from(self.clone()) { + return addr.fmt(f); + } + } + _ => {} } + + f.debug_struct("SocketAddrAny") + .field("address_family", &self.address_family()) + .field("namelen", &self.len()) + .finish() } } unsafe impl SocketAddrArg for SocketAddrAny { fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { - match self { - Self::V4(a) => a.with_sockaddr(f), - Self::V6(a) => a.with_sockaddr(f), - #[cfg(unix)] - Self::Unix(a) => a.with_sockaddr(f), - #[cfg(target_os = "linux")] - Self::Xdp(a) => a.with_sockaddr(f), + f(self.as_ptr().cast(), self.len()) + } +} + +impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddr) -> Self { + from.as_any() + } +} + +impl TryFrom for SocketAddr { + type Error = Errno; + + /// Convert if the address is an IPv4 or IPv6 address. + /// + /// Returns `Err(Errno::AFNOSUPPORT)` if the address family is not IPv4 or IPv6. + #[inline] + fn try_from(value: SocketAddrAny) -> Result { + match value.address_family() { + AddressFamily::INET => read_sockaddr::read_sockaddr_v4(&value).map(SocketAddr::V4), + AddressFamily::INET6 => read_sockaddr::read_sockaddr_v6(&value).map(SocketAddr::V6), + _ => Err(Errno::AFNOSUPPORT), } } } + +impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddrV4) -> Self { + from.as_any() + } +} + +impl TryFrom for SocketAddrV4 { + type Error = Errno; + + /// Convert if the address is an IPv4 address. + /// + /// Returns `Err(Errno::AFNOSUPPORT)` if the address family is not IPv4. + #[inline] + fn try_from(value: SocketAddrAny) -> Result { + read_sockaddr::read_sockaddr_v4(&value) + } +} + +impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddrV6) -> Self { + from.as_any() + } +} + +impl TryFrom for SocketAddrV6 { + type Error = Errno; + + /// Convert if the address is an IPv6 address. + /// + /// Returns `Err(Errno::AFNOSUPPORT)` if the address family is not IPv6. + #[inline] + fn try_from(value: SocketAddrAny) -> Result { + read_sockaddr::read_sockaddr_v6(&value) + } +} + +#[cfg(unix)] +impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddrUnix) -> Self { + from.as_any() + } +} + +#[cfg(unix)] +impl TryFrom for SocketAddrUnix { + type Error = Errno; + + /// Convert if the address is a Unix socket address. + /// + /// Returns `Err(Errno::AFNOSUPPORT)` if the address family is not Unix. + #[inline] + fn try_from(value: SocketAddrAny) -> Result { + read_sockaddr::read_sockaddr_unix(&value) + } +} diff --git a/src/net/types.rs b/src/net/types.rs index e401098a3..d58931784 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -1539,7 +1539,11 @@ bitflags! { /// `AF_XDP` related types and constants. #[cfg(target_os = "linux")] pub mod xdp { - use crate::net::addr::{call_with_sockaddr, SocketAddrArg, SocketAddrOpaque}; + use crate::backend::net::read_sockaddr::read_sockaddr_xdp; + use crate::net::{ + addr::{call_with_sockaddr, SocketAddrArg, SocketAddrOpaque}, + SocketAddrAny, + }; use super::{bitflags, c}; @@ -1695,6 +1699,21 @@ pub mod xdp { } } + impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddrXdp) -> Self { + from.as_any() + } + } + + impl TryFrom for SocketAddrXdp { + type Error = crate::io::Errno; + + fn try_from(addr: SocketAddrAny) -> Result { + read_sockaddr_xdp(&addr) + } + } + /// XDP ring offset. /// /// Used to mmap rings from kernel. diff --git a/tests/event/epoll.rs b/tests/event/epoll.rs index 4d9378648..3a58bf85d 100644 --- a/tests/event/epoll.rs +++ b/tests/event/epoll.rs @@ -2,7 +2,7 @@ use rustix::event::epoll; use rustix::io::{ioctl_fionbio, read, write}; use rustix::net::{ accept, bind_v4, connect_v4, getsockname, listen, socket, AddressFamily, Ipv4Addr, - SocketAddrAny, SocketAddrV4, SocketType, + SocketAddrV4, SocketType, }; use std::collections::HashMap; use std::ffi::c_void; @@ -16,10 +16,7 @@ fn server(ready: Arc<(Mutex, Condvar)>) { bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap(); listen(&listen_sock, 1).unwrap(); - let who = match getsockname(&listen_sock).unwrap() { - SocketAddrAny::V4(addr) => addr, - _ => panic!(), - }; + let who = SocketAddrV4::try_from(getsockname(&listen_sock).unwrap()).unwrap(); { let (lock, cvar) = &*ready; diff --git a/tests/net/addr.rs b/tests/net/addr.rs index d3f2aaf6b..39363c44e 100644 --- a/tests/net/addr.rs +++ b/tests/net/addr.rs @@ -2,31 +2,24 @@ fn encode_decode() { #[cfg(unix)] use rustix::net::SocketAddrUnix; - use rustix::net::{ - addr::SocketAddrStorage, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6, - }; + use rustix::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; - unsafe { - let orig = SocketAddrV4::new(Ipv4Addr::new(2, 3, 5, 6), 33); - let mut encoded = std::mem::MaybeUninit::::uninit(); - let len = SocketAddrAny::V4(orig).write(encoded.as_mut_ptr()); - let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap(); - assert_eq!(decoded, SocketAddrAny::V4(orig)); + let orig = SocketAddrV4::new(Ipv4Addr::new(2, 3, 5, 6), 33); + let encoded = SocketAddrAny::from(orig); + let decoded = SocketAddrV4::try_from(encoded).unwrap(); + assert_eq!(decoded, orig); - let orig = SocketAddrV6::new(Ipv6Addr::new(2, 3, 5, 6, 8, 9, 11, 12), 33, 34, 36); - let mut encoded = std::mem::MaybeUninit::::uninit(); - let len = SocketAddrAny::V6(orig).write(encoded.as_mut_ptr()); - let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap(); - assert_eq!(decoded, SocketAddrAny::V6(orig)); + let orig = SocketAddrV6::new(Ipv6Addr::new(2, 3, 5, 6, 8, 9, 11, 12), 33, 34, 36); + let encoded = SocketAddrAny::from(orig.clone()); + let decoded = SocketAddrV6::try_from(encoded).unwrap(); + assert_eq!(decoded, orig); - #[cfg(not(windows))] - { - let orig = SocketAddrUnix::new("/path/to/socket").unwrap(); - let mut encoded = std::mem::MaybeUninit::::uninit(); - let len = SocketAddrAny::Unix(orig.clone()).write(encoded.as_mut_ptr()); - let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap(); - assert_eq!(decoded, SocketAddrAny::Unix(orig)); - } + #[cfg(not(windows))] + { + let orig = SocketAddrUnix::new("/path/to/socket").unwrap(); + let encoded = SocketAddrAny::from(orig.clone()); + let decoded = SocketAddrUnix::try_from(encoded).unwrap(); + assert_eq!(decoded, orig); } } diff --git a/tests/net/connect_bind_send.rs b/tests/net/connect_bind_send.rs index 05eae1990..51f548c1b 100644 --- a/tests/net/connect_bind_send.rs +++ b/tests/net/connect_bind_send.rs @@ -1,8 +1,7 @@ #[cfg(not(any(apple, windows, target_os = "haiku")))] use rustix::net::SocketFlags; use rustix::net::{ - AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6, - SocketType, + AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV4, SocketAddrV6, SocketType, }; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -148,10 +147,7 @@ fn net_v4_connect() { rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => SocketAddr::V4(v4), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).expect("unexpected socket address"); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; @@ -183,8 +179,8 @@ fn net_v6_connect() { rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => SocketAddr::V6(v6), + let local_addr = match SocketAddrV6::try_from(local_addr) { + Ok(v6) => SocketAddr::V6(v6), other => panic!("unexpected socket address {:?}", other), }; let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); @@ -237,17 +233,13 @@ fn net_v4_connect_unspec() { assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); fn getsockname_v4(sockfd: Fd) -> rustix::io::Result { - match rustix::net::getsockname(sockfd)? { - SocketAddrAny::V4(addr_v4) => Ok(addr_v4), - _ => Err(rustix::io::Errno::AFNOSUPPORT), - } + rustix::net::getsockname(sockfd)?.try_into() } fn getpeername_v4(sockfd: Fd) -> rustix::io::Result { match rustix::net::getpeername(sockfd)? { - Some(SocketAddrAny::V4(addr_v4)) => Ok(addr_v4), + Some(addr) => addr.try_into(), None => Err(rustix::io::Errno::NOTCONN), - _ => Err(rustix::io::Errno::AFNOSUPPORT), } } } @@ -283,17 +275,13 @@ fn net_v6_connect_unspec() { assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); fn getsockname_v6(sockfd: Fd) -> rustix::io::Result { - match rustix::net::getsockname(sockfd)? { - SocketAddrAny::V6(addr_v6) => Ok(addr_v6), - _ => Err(rustix::io::Errno::AFNOSUPPORT), - } + rustix::net::getsockname(sockfd)?.try_into() } fn getpeername_v6(sockfd: Fd) -> rustix::io::Result { match rustix::net::getpeername(sockfd)? { - Some(SocketAddrAny::V6(addr_v6)) => Ok(addr_v6), + Some(addr) => addr.try_into(), None => Err(rustix::io::Errno::NOTCONN), - _ => Err(rustix::io::Errno::AFNOSUPPORT), } } } @@ -335,7 +323,7 @@ fn net_v6_bind_any() { crate::init(); let localhost = Ipv6Addr::LOCALHOST; - let addr = SocketAddrAny::V6(SocketAddrV6::new(localhost, 0, 0, 0)); + let addr = SocketAddrV6::new(localhost, 0, 0, 0).into(); let listener = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); rustix::net::bind_any(&listener, &addr).expect("bind"); rustix::net::listen(&listener, 1).expect("listen"); @@ -375,10 +363,7 @@ fn net_v4_sendto() { let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); rustix::net::connect_any(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => SocketAddr::V4(v4), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).expect("unexpected socket address"); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -412,10 +397,7 @@ fn net_v6_sendto() { let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); rustix::net::connect_any(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => SocketAddr::V6(v6), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV6::try_from(local_addr).expect("unexpected socket address"); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -527,24 +509,15 @@ fn net_v4_acceptfrom() { assert_ne!(from.clone().unwrap(), local_addr); - let from = match from.unwrap() { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let from = SocketAddrV4::try_from(from.unwrap()).unwrap(); + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); assert_eq!(from.clone().ip(), local_addr.ip()); assert_ne!(from.clone().port(), local_addr.port()); let peer_addr = rustix::net::getpeername(&accepted).expect("getpeername"); let peer_addr = peer_addr.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV4::try_from(peer_addr).unwrap(); assert_eq!(from.clone().ip(), peer_addr.ip()); assert_eq!(from.clone().port(), peer_addr.port()); @@ -583,24 +556,15 @@ fn net_v6_acceptfrom() { assert_ne!(from.clone().unwrap(), local_addr); - let from = match from.unwrap() { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let from = SocketAddrV6::try_from(from.unwrap()).unwrap(); + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); assert_eq!(from.clone().ip(), local_addr.ip()); assert_ne!(from.clone().port(), local_addr.port()); let peer_addr = rustix::net::getpeername(&accepted).expect("getpeername"); let peer_addr = peer_addr.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV6::try_from(peer_addr).unwrap(); assert_eq!(from.clone().ip(), peer_addr.ip()); assert_eq!(from.clone().port(), peer_addr.port()); diff --git a/tests/net/dgram.rs b/tests/net/dgram.rs index 19021c5a2..05c5acecf 100644 --- a/tests/net/dgram.rs +++ b/tests/net/dgram.rs @@ -1,8 +1,7 @@ //! Tests similar to connect_bind_send.rs, but operating on datagram sockets. use rustix::net::{ - AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6, - SocketType, + AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV4, SocketAddrV6, SocketType, }; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -139,10 +138,7 @@ fn net_dgram_v4_connect() { rustix::net::bind(&listener, &addr).expect("bind"); let local_addr = rustix::net::getsockname(&listener).unwrap(); - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => SocketAddr::V4(v4), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; @@ -172,10 +168,7 @@ fn net_dgram_v6_connect() { rustix::net::bind(&listener, &addr).expect("bind"); let local_addr = rustix::net::getsockname(&listener).unwrap(); - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => SocketAddr::V6(v6), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; @@ -225,17 +218,13 @@ fn net_dgram_v4_connect_unspec() { assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); fn getsockname_v4(sockfd: Fd) -> rustix::io::Result { - match rustix::net::getsockname(sockfd)? { - SocketAddrAny::V4(addr_v4) => Ok(addr_v4), - _ => Err(rustix::io::Errno::AFNOSUPPORT), - } + rustix::net::getsockname(sockfd)?.try_into() } fn getpeername_v4(sockfd: Fd) -> rustix::io::Result { match rustix::net::getpeername(sockfd)? { - Some(SocketAddrAny::V4(addr_v4)) => Ok(addr_v4), + Some(addr) => addr.try_into(), None => Err(rustix::io::Errno::NOTCONN), - _ => Err(rustix::io::Errno::AFNOSUPPORT), } } } @@ -271,17 +260,13 @@ fn net_dgram_v6_connect_unspec() { assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); fn getsockname_v6(sockfd: Fd) -> rustix::io::Result { - match rustix::net::getsockname(sockfd)? { - SocketAddrAny::V6(addr_v6) => Ok(addr_v6), - _ => Err(rustix::io::Errno::AFNOSUPPORT), - } + rustix::net::getsockname(sockfd)?.try_into() } fn getpeername_v6(sockfd: Fd) -> rustix::io::Result { match rustix::net::getpeername(sockfd)? { - Some(SocketAddrAny::V6(addr_v6)) => Ok(addr_v6), + Some(addr) => addr.try_into(), None => Err(rustix::io::Errno::NOTCONN), - _ => Err(rustix::io::Errno::AFNOSUPPORT), } } } @@ -321,7 +306,7 @@ fn net_dgram_v6_bind_any() { crate::init(); let localhost = Ipv6Addr::LOCALHOST; - let addr = SocketAddrAny::V6(SocketAddrV6::new(localhost, 0, 0, 0)); + let addr = SocketAddrV6::new(localhost, 0, 0, 0).into(); let listener = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); rustix::net::bind_any(&listener, &addr).expect("bind"); @@ -359,10 +344,7 @@ fn net_dgram_v4_connect_sendto() { let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); rustix::net::connect_any(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => SocketAddr::V4(v4), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -379,15 +361,9 @@ fn net_dgram_v4_connect_sendto() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV4::try_from(peer_addr).unwrap(); - let local_addr = match local_addr { - SocketAddr::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -405,10 +381,7 @@ fn net_dgram_v4_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => SocketAddr::V4(v4), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -425,15 +398,9 @@ fn net_dgram_v4_sendto() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV4::try_from(peer_addr).unwrap(); - let local_addr = match local_addr { - SocketAddr::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -453,10 +420,7 @@ fn net_dgram_v6_connect_sendto() { let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); rustix::net::connect_any(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => SocketAddr::V6(v6), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -473,16 +437,9 @@ fn net_dgram_v6_connect_sendto() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; - - let local_addr = match local_addr { - SocketAddr::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV6::try_from(peer_addr).unwrap(); + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -499,10 +456,7 @@ fn net_dgram_v6_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => SocketAddr::V6(v6), - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); @@ -519,16 +473,9 @@ fn net_dgram_v6_sendto() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; - - let local_addr = match local_addr { - SocketAddr::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV6::try_from(peer_addr).unwrap(); + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -564,16 +511,9 @@ fn net_dgram_v4_connect_sendto_any() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; - - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV4::try_from(peer_addr).unwrap(); + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -607,16 +547,9 @@ fn net_dgram_v4_sendto_any() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; - - let local_addr = match local_addr { - SocketAddrAny::V4(v4) => v4, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV4::try_from(peer_addr).unwrap(); + let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -652,15 +585,9 @@ fn net_dgram_v6_connect_sendto_any() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV6::try_from(peer_addr).unwrap(); - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } @@ -695,15 +622,9 @@ fn net_dgram_v6_sendto_any() { assert_eq!(request, &response[..n]); let peer_addr = from.expect("peer address should be available"); - let peer_addr = match peer_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; - - let local_addr = match local_addr { - SocketAddrAny::V6(v6) => v6, - other => panic!("unexpected socket address {:?}", other), - }; + let peer_addr = SocketAddrV6::try_from(peer_addr).unwrap(); + + let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); assert_eq!(peer_addr.ip(), local_addr.ip()); } diff --git a/tests/net/poll.rs b/tests/net/poll.rs index 31c35349a..c53078eb0 100644 --- a/tests/net/poll.rs +++ b/tests/net/poll.rs @@ -5,7 +5,7 @@ use rustix::event::{poll, PollFd, PollFlags}; use rustix::net::{ accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, - RecvFlags, SendFlags, SocketAddrAny, SocketAddrV6, SocketType, + RecvFlags, SendFlags, SocketAddrV6, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; use std::thread; @@ -18,10 +18,8 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); bind_v6(&connection_socket, &name).unwrap(); - let who = match getsockname(&connection_socket).unwrap() { - SocketAddrAny::V6(addr) => addr, - _ => panic!(), - }; + let who = getsockname(&connection_socket).unwrap(); + let who = SocketAddrV6::try_from(who).unwrap(); listen(&connection_socket, 1).unwrap(); diff --git a/tests/net/unix.rs b/tests/net/unix.rs index f003cd1db..256c753ab 100644 --- a/tests/net/unix.rs +++ b/tests/net/unix.rs @@ -222,10 +222,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { // `SocketAddrUnix::path()` returned `None` for some reason. // illumos and NetBSD too. #[cfg(not(any(solarish, target_os = "freebsd", target_os = "netbsd")))] - assert_eq!( - Some(rustix::net::SocketAddrAny::Unix(addr.clone())), - result.address - ); + assert_eq!(Some(addr.clone().into()), result.address); } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); @@ -946,10 +943,7 @@ fn test_bind_unnamed_address() { bind_unix(&sock, &address).unwrap(); let address = rustix::net::getsockname(&sock).unwrap(); - let address = match address { - rustix::net::SocketAddrAny::Unix(address) => address, - address => panic!("expected Unix address, got {address:?}"), - }; + let address = SocketAddrUnix::try_from(address).unwrap(); assert!(!address.is_unnamed()); assert_ne!(address.abstract_name(), None); assert_eq!(address.path(), None); diff --git a/tests/net/unix_alloc.rs b/tests/net/unix_alloc.rs index d91dca6fc..6580ce5b2 100644 --- a/tests/net/unix_alloc.rs +++ b/tests/net/unix_alloc.rs @@ -219,10 +219,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { // `SocketAddrUnix::path()` returned `None` for some reason. // illumos and NetBSD too. #[cfg(not(any(solarish, target_os = "freebsd", target_os = "netbsd")))] - assert_eq!( - Some(rustix::net::SocketAddrAny::Unix(addr.clone())), - result.address - ); + assert_eq!(Some(addr.clone().into()), result.address); } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); diff --git a/tests/net/v4.rs b/tests/net/v4.rs index 5068c5f96..b2a2f08ca 100644 --- a/tests/net/v4.rs +++ b/tests/net/v4.rs @@ -8,7 +8,7 @@ use rustix::net::ReturnFlags; use rustix::net::{ accept, bind_v4, connect_v4, getsockname, listen, recv, send, socket, AddressFamily, Ipv4Addr, - RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketType, + RecvFlags, SendFlags, SocketAddrV4, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; use std::thread; @@ -21,10 +21,8 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0); bind_v4(&connection_socket, &name).unwrap(); - let who = match getsockname(&connection_socket).unwrap() { - SocketAddrAny::V4(addr) => addr, - _ => panic!(), - }; + let who = getsockname(&connection_socket).unwrap(); + let who = SocketAddrV4::try_from(who).unwrap(); listen(&connection_socket, 1).unwrap(); @@ -102,10 +100,8 @@ fn test_v4_msg() { let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0); bind_v4(&connection_socket, &name).unwrap(); - let who = match getsockname(&connection_socket).unwrap() { - SocketAddrAny::V4(addr) => addr, - _ => panic!(), - }; + let who = getsockname(&connection_socket).unwrap(); + let who = SocketAddrV4::try_from(who).unwrap(); listen(&connection_socket, 1).unwrap(); diff --git a/tests/net/v6.rs b/tests/net/v6.rs index 8b325330c..20611b47b 100644 --- a/tests/net/v6.rs +++ b/tests/net/v6.rs @@ -8,7 +8,7 @@ use rustix::net::ReturnFlags; use rustix::net::{ accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, - RecvFlags, SendFlags, SocketAddrAny, SocketAddrV6, SocketType, + RecvFlags, SendFlags, SocketAddrV6, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; use std::thread; @@ -21,10 +21,8 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); bind_v6(&connection_socket, &name).unwrap(); - let who = match getsockname(&connection_socket).unwrap() { - SocketAddrAny::V6(addr) => addr, - _ => panic!(), - }; + let who = getsockname(&connection_socket).unwrap(); + let who = SocketAddrV6::try_from(who).unwrap(); listen(&connection_socket, 1).unwrap(); @@ -102,10 +100,8 @@ fn test_v6_msg() { let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); bind_v6(&connection_socket, &name).unwrap(); - let who = match getsockname(&connection_socket).unwrap() { - SocketAddrAny::V6(addr) => addr, - _ => panic!(), - }; + let who = getsockname(&connection_socket).unwrap(); + let who = SocketAddrV6::try_from(who).unwrap(); listen(&connection_socket, 1).unwrap(); From 880bbd3249d163864493e62594041d37b0506e73 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 1 Feb 2025 14:11:22 -0700 Subject: [PATCH 4/5] Remove address type variants of `bind`, `connect`, `sendmsg`, `sendto` Removes: * `bind_any`, `bind_unix`, `bind_v4`, `bind_v6`, `bind_xdp` in favor of `bind`, * `connect_any`, `connect_unix`, `connect_v4`, `connect_v6` in favor of `connect` (leaving address-less `connect_unspec`) * `sendmsg_v4`, `sendmsg_v6`, `sendmsg_unix`, `sendmsg_xdp`, `sendmsg_any` in favor of `sendmsg_addr` (leaving address-less `sendmsg`) * `sendto_any`, `sendto_v4`, `sendto_v6`, `sendto_unix`, `sendto_xdp` in favor of `sendto` --- src/event/epoll.rs | 4 +- src/net/send_recv/mod.rs | 176 +-------------------- src/net/send_recv/msg.rs | 160 +------------------ src/net/socket.rs | 279 +-------------------------------- tests/event/epoll.rs | 8 +- tests/event/select.rs | 4 +- tests/net/connect_bind_send.rs | 59 ++++--- tests/net/dgram.rs | 61 ++++--- tests/net/poll.rs | 6 +- tests/net/recv_trunc.rs | 19 +-- tests/net/unix.rs | 40 ++--- tests/net/unix_alloc.rs | 38 ++--- tests/net/v4.rs | 10 +- tests/net/v6.rs | 10 +- 14 files changed, 132 insertions(+), 742 deletions(-) diff --git a/src/event/epoll.rs b/src/event/epoll.rs index daa200adb..5fb2eccdc 100644 --- a/src/event/epoll.rs +++ b/src/event/epoll.rs @@ -9,14 +9,14 @@ //! use rustix::fd::AsFd; //! use rustix::io::{ioctl_fionbio, read, write}; //! use rustix::net::{ -//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType, +//! accept, bind, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType, //! }; //! use std::collections::HashMap; //! use std::os::unix::io::AsRawFd; //! //! // Create a socket and listen on it. //! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?; -//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; +//! bind(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; //! listen(&listen_sock, 1)?; //! //! // Create an epoll object. Using `Owning` here means the epoll object will diff --git a/src/net/send_recv/mod.rs b/src/net/send_recv/mod.rs index 41cd48538..5753ff8b8 100644 --- a/src/net/send_recv/mod.rs +++ b/src/net/send_recv/mod.rs @@ -3,11 +3,7 @@ #![allow(unsafe_code)] use crate::buffer::split_init; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; -#[cfg(unix)] -use crate::net::SocketAddrUnix; -use crate::net::{addr::SocketAddrArg, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::net::{addr::SocketAddrArg, SocketAddrAny}; use crate::{backend, io}; use backend::fd::AsFd; use core::cmp::min; @@ -217,173 +213,3 @@ pub fn sendto( ) -> io::Result { backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) } - -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Sending-Datagrams.html -pub fn sendto_any( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrAny, -) -> io::Result { - backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) -} - -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Sending-Datagrams.html -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_v4( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV4, -) -> io::Result { - backend::net::syscalls::sendto(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Sending-Datagrams.html -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_v6( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV6, -) -> io::Result { - backend::net::syscalls::sendto(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Sending-Datagrams.html -#[cfg(unix)] -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_unix( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrUnix, -) -> io::Result { - backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) -} - -/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_xdp))`—Writes data -/// to a socket to a specific XDP address. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -#[cfg(target_os = "linux")] -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_xdp( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrXdp, -) -> io::Result { - backend::net::syscalls::sendto(fd.as_fd(), buf, flags, addr) -} diff --git a/src/net/send_recv/msg.rs b/src/net/send_recv/msg.rs index d21a9646b..72e12fc79 100644 --- a/src/net/send_recv/msg.rs +++ b/src/net/send_recv/msg.rs @@ -17,7 +17,7 @@ use core::mem::{align_of, size_of, size_of_val, take}; use core::ptr::addr_of; use core::{ptr, slice}; -use super::{RecvFlags, ReturnFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use super::{RecvFlags, ReturnFlags, SendFlags, SocketAddrAny}; /// Macro for defining the amount of space to allocate in a buffer for use with /// [`RecvAncillaryBuffer::new`] and [`SendAncillaryBuffer::new`]. @@ -122,8 +122,7 @@ pub const fn __cmsg_aligned_space(len: usize) -> usize { unsafe { c::CMSG_SPACE(converted_len) as usize } } -/// Ancillary message for [`sendmsg`], [`sendmsg_v4`], [`sendmsg_v6`], -/// [`sendmsg_unix`], and [`sendmsg_any`]. +/// Ancillary message for [`sendmsg`] and [`sendmsg_addr`]. #[non_exhaustive] pub enum SendAncillaryMessage<'slice, 'fd> { /// Send file descriptors. @@ -160,8 +159,7 @@ pub enum RecvAncillaryMessage<'a> { ScmCredentials(UCred), } -/// Buffer for sending ancillary messages with [`sendmsg`], [`sendmsg_v4`], -/// [`sendmsg_v6`], [`sendmsg_unix`], and [`sendmsg_any`]. +/// Buffer for sending ancillary messages with [`sendmsg`] and [`sendmsg_addr`]. /// /// Use the [`push`] function to add messages to send. /// @@ -596,8 +594,7 @@ impl FusedIterator for AncillaryDrain<'_> {} /// `sendmsg(msghdr)`—Sends a message on a socket. /// /// This function is for use on connected sockets, as it doesn't have -/// a way to specify an address. See the [`sendmsg_v4`], [`sendmsg_v6`] -/// [`sendmsg_unix`], [`sendmsg_xdp`], and [`sendmsg_any`] to send +/// a way to specify an address. See [`sendmsg_addr`] to send /// messages on unconnected sockets. /// /// # References @@ -659,155 +656,6 @@ pub fn sendmsg_addr( backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, 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/9799919799/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: Fd, - addr: &SocketAddrV4, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - flags: SendFlags, -) -> io::Result { - backend::net::syscalls::sendmsg_addr(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/9799919799/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: Fd, - addr: &SocketAddrV6, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - flags: SendFlags, -) -> io::Result { - backend::net::syscalls::sendmsg_addr(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/9799919799/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: Fd, - addr: &super::SocketAddrUnix, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - flags: SendFlags, -) -> io::Result { - backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) -} - -/// `sendmsg(msghdr)`—Sends a message on a socket to a specific XDP address. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html -#[inline] -#[cfg(target_os = "linux")] -pub fn sendmsg_xdp( - socket: Fd, - addr: &super::SocketAddrXdp, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - flags: SendFlags, -) -> io::Result { - backend::net::syscalls::sendmsg_addr(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/9799919799/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: Fd, - addr: Option<&SocketAddrAny>, - iov: &[IoSlice<'_>], - control: &mut SendAncillaryBuffer<'_, '_, '_>, - flags: SendFlags, -) -> io::Result { - match addr { - None => backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags), - Some(addr) => { - backend::net::syscalls::sendmsg_addr(socket.as_fd(), addr, iov, control, flags) - } - } -} - /// `recvmsg(msghdr)`—Receives a message from a socket. /// /// # References diff --git a/src/net/socket.rs b/src/net/socket.rs index 6314ef223..459e86fd8 100644 --- a/src/net/socket.rs +++ b/src/net/socket.rs @@ -1,10 +1,8 @@ use crate::fd::OwnedFd; -use crate::net::{addr::SocketAddrArg, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::net::{addr::SocketAddrArg, SocketAddrAny}; use crate::{backend, io}; use backend::fd::AsFd; -#[cfg(target_os = "linux")] -use crate::net::xdp::SocketAddrXdp; pub use crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; #[cfg(unix)] pub use backend::net::addr::SocketAddrUnix; @@ -126,150 +124,6 @@ pub fn bind(sockfd: Fd, addr: &impl SocketAddrArg) -> io::Result<()> { backend::net::syscalls::bind(sockfd.as_fd(), addr) } -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html -#[doc(alias = "bind")] -pub fn bind_any(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> { - backend::net::syscalls::bind(sockfd.as_fd(), addr) -} - -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html -#[inline] -#[doc(alias = "bind")] -pub fn bind_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { - backend::net::syscalls::bind(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html -#[inline] -#[doc(alias = "bind")] -pub fn bind_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { - backend::net::syscalls::bind(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Setting-Address.html -#[cfg(unix)] -#[inline] -#[doc(alias = "bind")] -pub fn bind_unix(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { - backend::net::syscalls::bind(sockfd.as_fd(), addr) -} - -/// `bind(sockfd, addr, sizeof(struct sockaddr_xdp))`—Binds a socket to a XDP address. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/bind.2.html -#[cfg(target_os = "linux")] -#[inline] -#[doc(alias = "bind")] -pub fn bind_xdp(sockfd: Fd, addr: &SocketAddrXdp) -> io::Result<()> { - backend::net::syscalls::bind(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 @@ -305,137 +159,6 @@ pub fn connect(sockfd: Fd, addr: &impl SocketAddrArg) -> io::Result<() backend::net::syscalls::connect(sockfd.as_fd(), addr) } -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Connecting.html -#[doc(alias = "connect")] -pub fn connect_any(sockfd: Fd, addr: &SocketAddrAny) -> io::Result<()> { - backend::net::syscalls::connect(sockfd.as_fd(), addr) -} - -/// `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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Connecting.html -#[inline] -#[doc(alias = "connect")] -pub fn connect_v4(sockfd: Fd, addr: &SocketAddrV4) -> io::Result<()> { - backend::net::syscalls::connect(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Connecting.html -#[inline] -#[doc(alias = "connect")] -pub fn connect_v6(sockfd: Fd, addr: &SocketAddrV6) -> io::Result<()> { - backend::net::syscalls::connect(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/9799919799/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://sourceware.org/glibc/manual/latest/html_node/Connecting.html -#[cfg(unix)] -#[inline] -#[doc(alias = "connect")] -pub fn connect_unix(sockfd: Fd, addr: &SocketAddrUnix) -> io::Result<()> { - backend::net::syscalls::connect(sockfd.as_fd(), addr) -} - /// `connect(sockfd, {.sa_family = AF_UNSPEC}, sizeof(struct sockaddr))`— /// Dissolve the socket's association. /// diff --git a/tests/event/epoll.rs b/tests/event/epoll.rs index 3a58bf85d..b2cc9367e 100644 --- a/tests/event/epoll.rs +++ b/tests/event/epoll.rs @@ -1,8 +1,8 @@ use rustix::event::epoll; use rustix::io::{ioctl_fionbio, read, write}; use rustix::net::{ - accept, bind_v4, connect_v4, getsockname, listen, socket, AddressFamily, Ipv4Addr, - SocketAddrV4, SocketType, + accept, bind, connect, getsockname, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, + SocketType, }; use std::collections::HashMap; use std::ffi::c_void; @@ -13,7 +13,7 @@ const BUFFER_SIZE: usize = 20; fn server(ready: Arc<(Mutex, Condvar)>) { let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap(); + bind(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap(); listen(&listen_sock, 1).unwrap(); let who = SocketAddrV4::try_from(getsockname(&listen_sock).unwrap()).unwrap(); @@ -79,7 +79,7 @@ fn client(ready: Arc<(Mutex, Condvar)>) { for _ in 0..16 { let data_socket = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - connect_v4(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); let nread = read(&data_socket, &mut buffer).unwrap(); assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello\n"); diff --git a/tests/event/select.rs b/tests/event/select.rs index a5f91b9d1..359d136bb 100644 --- a/tests/event/select.rs +++ b/tests/event/select.rs @@ -195,7 +195,7 @@ fn test_select_with_sockets() { rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let writer = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&writer, &local_addr).expect("connect"); + rustix::net::connect(&writer, &local_addr).expect("connect"); let reader = rustix::net::accept(&listener).expect("accept"); let nfds = max(reader.as_raw_fd(), writer.as_raw_fd()) + 1; @@ -290,7 +290,7 @@ fn test_select_with_maxfd_sockets() { rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let writer = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&writer, &local_addr).expect("connect"); + rustix::net::connect(&writer, &local_addr).expect("connect"); let reader = rustix::net::accept(&listener).expect("accept"); // Raise the fd limit to the maximum. diff --git a/tests/net/connect_bind_send.rs b/tests/net/connect_bind_send.rs index 51f548c1b..67cfe5030 100644 --- a/tests/net/connect_bind_send.rs +++ b/tests/net/connect_bind_send.rs @@ -1,11 +1,12 @@ #[cfg(not(any(apple, windows, target_os = "haiku")))] use rustix::net::SocketFlags; use rustix::net::{ - AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV4, SocketAddrV6, SocketType, + AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6, + SocketType, }; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -/// Test `connect_any`. +/// Test `connect` with `SocketAddrAny`. #[test] fn net_v4_connect_any() { crate::init(); @@ -19,7 +20,7 @@ fn net_v4_connect_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -37,7 +38,7 @@ fn net_v4_connect_any() { assert_eq!(request, &response[..n]); } -/// Test `connect_any` using `accept_with`. +/// Test `connect` with `SocketAddrAny` using `accept_with`. #[cfg(not(any(apple, windows, target_os = "haiku")))] #[test] fn net_v4_connect_any_accept_with() { @@ -52,7 +53,7 @@ fn net_v4_connect_any_accept_with() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World, with flags!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -84,7 +85,7 @@ fn net_v6_connect_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -117,7 +118,7 @@ fn net_v6_connect_any_accept_with() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World, with flags!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -212,7 +213,7 @@ fn net_v4_connect_unspec() { let socket = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_v4(&socket, &localhost_addr).expect("connect_v4"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v4"); assert_eq!(getsockname_v4(&socket).unwrap().ip(), &Ipv4Addr::LOCALHOST); assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); @@ -228,7 +229,7 @@ fn net_v4_connect_unspec() { ); assert_eq!(getpeername_v4(&socket), Err(rustix::io::Errno::NOTCONN)); - rustix::net::connect_v4(&socket, &localhost_addr).expect("connect_v4"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v4"); assert_eq!(getsockname_v4(&socket).unwrap().ip(), &Ipv4Addr::LOCALHOST); assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); @@ -254,7 +255,7 @@ fn net_v6_connect_unspec() { let socket = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_v6(&socket, &localhost_addr).expect("connect_v6"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v6"); assert_eq!(getsockname_v6(&socket).unwrap().ip(), &Ipv6Addr::LOCALHOST); assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); @@ -270,7 +271,7 @@ fn net_v6_connect_unspec() { ); assert_eq!(getpeername_v6(&socket), Err(rustix::io::Errno::NOTCONN)); - rustix::net::connect_v6(&socket, &localhost_addr).expect("connect_v6"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v6"); assert_eq!(getsockname_v6(&socket).unwrap().ip(), &Ipv6Addr::LOCALHOST); assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); @@ -286,20 +287,20 @@ fn net_v6_connect_unspec() { } } -/// Test `bind_any`. +/// Test `bind` with `SocketAddrAny`. #[test] fn net_v4_bind_any() { crate::init(); let localhost = Ipv4Addr::LOCALHOST; - let addr = SocketAddrV4::new(localhost, 0).into(); + let addr = SocketAddrAny::from(SocketAddrV4::new(localhost, 0)); let listener = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::bind_any(&listener, &addr).expect("bind"); + rustix::net::bind(&listener, &addr).expect("bind"); rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -323,14 +324,14 @@ fn net_v6_bind_any() { crate::init(); let localhost = Ipv6Addr::LOCALHOST; - let addr = SocketAddrV6::new(localhost, 0, 0, 0).into(); + let addr = SocketAddrAny::from(SocketAddrV6::new(localhost, 0, 0, 0)); let listener = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::bind_any(&listener, &addr).expect("bind"); + rustix::net::bind(&listener, &addr).expect("bind"); rustix::net::listen(&listener, 1).expect("listen"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -361,7 +362,7 @@ fn net_v4_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let local_addr = SocketAddrV4::try_from(local_addr).expect("unexpected socket address"); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); @@ -395,7 +396,7 @@ fn net_v6_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let local_addr = SocketAddrV6::try_from(local_addr).expect("unexpected socket address"); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); @@ -416,7 +417,7 @@ fn net_v6_sendto() { assert!(from.is_none()); } -/// Test `sendto_any`. +/// Test `sendto` with `SocketAddrAny`. #[test] fn net_v4_sendto_any() { crate::init(); @@ -429,10 +430,9 @@ fn net_v4_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -463,10 +463,9 @@ fn net_v6_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -497,7 +496,7 @@ fn net_v4_acceptfrom() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -544,7 +543,7 @@ fn net_v6_acceptfrom() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -592,7 +591,7 @@ fn net_shutdown() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); rustix::net::shutdown(&sender, rustix::net::Shutdown::Write).expect("shutdown"); let accepted = rustix::net::accept(&listener).expect("accept"); diff --git a/tests/net/dgram.rs b/tests/net/dgram.rs index 05c5acecf..383e29841 100644 --- a/tests/net/dgram.rs +++ b/tests/net/dgram.rs @@ -1,11 +1,12 @@ //! Tests similar to connect_bind_send.rs, but operating on datagram sockets. use rustix::net::{ - AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV4, SocketAddrV6, SocketType, + AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6, + SocketType, }; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -/// Test `connect_any`. +/// Test `connect` with `SocketAddrAny`. #[test] fn net_dgram_v4_connect_any() { crate::init(); @@ -18,7 +19,7 @@ fn net_dgram_v4_connect_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -35,7 +36,7 @@ fn net_dgram_v4_connect_any() { assert_eq!(request, &response[..n]); } -/// Test `connect_any` using `accept_with`. +/// Test `connect` with `SocketAddrAny` using `accept_with`. #[cfg(not(any(apple, windows, target_os = "haiku")))] #[test] fn net_dgram_v4_connect_any_accept_with() { @@ -49,7 +50,7 @@ fn net_dgram_v4_connect_any_accept_with() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World, with flags!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -79,7 +80,7 @@ fn net_dgram_v6_connect_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -110,7 +111,7 @@ fn net_dgram_v6_connect_any_accept_with() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World, with flags!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -197,7 +198,7 @@ fn net_dgram_v4_connect_unspec() { let socket = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_v4(&socket, &localhost_addr).expect("connect_v4"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v4"); assert_eq!(getsockname_v4(&socket).unwrap().ip(), &Ipv4Addr::LOCALHOST); assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); @@ -213,7 +214,7 @@ fn net_dgram_v4_connect_unspec() { ); assert_eq!(getpeername_v4(&socket), Err(rustix::io::Errno::NOTCONN)); - rustix::net::connect_v4(&socket, &localhost_addr).expect("connect_v4"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v4"); assert_eq!(getsockname_v4(&socket).unwrap().ip(), &Ipv4Addr::LOCALHOST); assert_eq!(getpeername_v4(&socket).unwrap(), localhost_addr); @@ -239,7 +240,7 @@ fn net_dgram_v6_connect_unspec() { let socket = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_v6(&socket, &localhost_addr).expect("connect_v6"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v6"); assert_eq!(getsockname_v6(&socket).unwrap().ip(), &Ipv6Addr::LOCALHOST); assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); @@ -255,7 +256,7 @@ fn net_dgram_v6_connect_unspec() { ); assert_eq!(getpeername_v6(&socket), Err(rustix::io::Errno::NOTCONN)); - rustix::net::connect_v6(&socket, &localhost_addr).expect("connect_v6"); + rustix::net::connect(&socket, &localhost_addr).expect("connect_v6"); assert_eq!(getsockname_v6(&socket).unwrap().ip(), &Ipv6Addr::LOCALHOST); assert_eq!(getpeername_v6(&socket).unwrap(), localhost_addr); @@ -271,19 +272,19 @@ fn net_dgram_v6_connect_unspec() { } } -/// Test `bind_any`. +/// Test `bind` with `SocketAddrAny`. #[test] fn net_dgram_v4_bind_any() { crate::init(); let localhost = Ipv4Addr::LOCALHOST; - let addr = SocketAddrV4::new(localhost, 0).into(); + let addr = SocketAddrAny::from(SocketAddrV4::new(localhost, 0)); let listener = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::bind_any(&listener, &addr).expect("bind"); + rustix::net::bind(&listener, &addr).expect("bind"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -306,13 +307,13 @@ fn net_dgram_v6_bind_any() { crate::init(); let localhost = Ipv6Addr::LOCALHOST; - let addr = SocketAddrV6::new(localhost, 0, 0, 0).into(); + let addr = SocketAddrAny::from(SocketAddrV6::new(localhost, 0, 0, 0)); let listener = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::bind_any(&listener, &addr).expect("bind"); + rustix::net::bind(&listener, &addr).expect("bind"); let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -342,7 +343,7 @@ fn net_dgram_v4_connect_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let local_addr = SocketAddrV4::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); @@ -418,7 +419,7 @@ fn net_dgram_v6_connect_sendto() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let local_addr = SocketAddrV6::try_from(local_addr).unwrap(); let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); @@ -492,10 +493,9 @@ fn net_dgram_v4_connect_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -530,8 +530,7 @@ fn net_dgram_v4_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -566,10 +565,9 @@ fn net_dgram_v6_connect_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -605,8 +603,7 @@ fn net_dgram_v6_sendto_any() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; - let n = - rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send"); drop(sender); // Not strictly required, but it makes the test simpler. @@ -641,7 +638,7 @@ fn net_dgram_v4_acceptfrom() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); @@ -670,7 +667,7 @@ fn net_dgram_v6_acceptfrom() { let local_addr = rustix::net::getsockname(&listener).unwrap(); let sender = rustix::net::socket(AddressFamily::INET6, SocketType::DGRAM, None).unwrap(); - rustix::net::connect_any(&sender, &local_addr).expect("connect"); + rustix::net::connect(&sender, &local_addr).expect("connect"); let request = b"Hello, World!!!"; let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send"); drop(sender); diff --git a/tests/net/poll.rs b/tests/net/poll.rs index c53078eb0..9d613c312 100644 --- a/tests/net/poll.rs +++ b/tests/net/poll.rs @@ -4,7 +4,7 @@ use rustix::event::{poll, PollFd, PollFlags}; use rustix::net::{ - accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, + accept, bind, connect, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV6, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; @@ -16,7 +16,7 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let connection_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); - bind_v6(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); let who = getsockname(&connection_socket).unwrap(); let who = SocketAddrV6::try_from(who).unwrap(); @@ -68,7 +68,7 @@ fn client(ready: Arc<(Mutex, Condvar)>) { let mut buffer = vec![0; BUFFER_SIZE]; let data_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - connect_v6(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); let mut fds = [PollFd::new(&data_socket, PollFlags::OUT)]; assert_eq!(poll(&mut fds, -1).unwrap(), 1); diff --git a/tests/net/recv_trunc.rs b/tests/net/recv_trunc.rs index ffe3f9ead..e8957821a 100644 --- a/tests/net/recv_trunc.rs +++ b/tests/net/recv_trunc.rs @@ -15,11 +15,11 @@ fn net_recv_uninit_trunc() { let name = SocketAddrUnix::new(&path).unwrap(); let receiver = rustix::net::socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - rustix::net::bind_unix(&receiver, &name).expect("bind"); + rustix::net::bind(&receiver, &name).expect("bind"); let sender = rustix::net::socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; - let n = rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); // Test with `RecvFlags::TRUNC`, which is not supported on Apple, illumos, or NetBSD. @@ -35,8 +35,7 @@ fn net_recv_uninit_trunc() { assert!(uninit.is_empty()); // Send the message again. - let n = - rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); // Check the `length`. @@ -68,7 +67,7 @@ fn net_recvmsg_trunc() { let name = SocketAddrUnix::new(&path).unwrap(); let receiver = rustix::net::socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - rustix::net::bind_unix(&receiver, &name).expect("bind"); + rustix::net::bind(&receiver, &name).expect("bind"); let sender = rustix::net::socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); let request = b"Hello, World!!!"; @@ -76,8 +75,7 @@ fn net_recvmsg_trunc() { // Test with `RecvFlags::TRUNC`, which is not supported on Apple, illumos, or NetBSD. #[cfg(not(any(apple, solarish, target_os = "netbsd")))] { - let n = - rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); let mut response = [0_u8; 5]; @@ -96,8 +94,7 @@ fn net_recvmsg_trunc() { assert_eq!(result.flags, ReturnFlags::TRUNC); // Send the message again. - let n = - rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); // This time receive it with `TRUNC` and a big enough buffer. @@ -118,7 +115,7 @@ fn net_recvmsg_trunc() { } // Send the message again. - let n = rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); // This time receive it without `TRUNC` but a big enough buffer. @@ -138,7 +135,7 @@ fn net_recvmsg_trunc() { assert_eq!(result.flags, ReturnFlags::empty()); // Send the message again. - let n = rustix::net::sendto_unix(&sender, request, SendFlags::empty(), &name).expect("send"); + let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &name).expect("send"); assert_eq!(n, request.len()); // This time receive it without `TRUNC` and a small buffer. diff --git a/tests/net/unix.rs b/tests/net/unix.rs index 256c753ab..2e420d857 100644 --- a/tests/net/unix.rs +++ b/tests/net/unix.rs @@ -10,7 +10,7 @@ use rustix::fs::{unlinkat, AtFlags, CWD}; use rustix::io::{read, write}; use rustix::net::{ - accept, bind_unix, connect_unix, listen, socket, AddressFamily, SocketAddrUnix, SocketType, + accept, bind, connect, listen, socket, AddressFamily, SocketAddrUnix, SocketType, }; use rustix::path::DecInt; use std::path::Path; @@ -24,7 +24,7 @@ fn server(ready: Arc<(Mutex, Condvar)>, path: &Path) { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); { @@ -71,7 +71,7 @@ fn client(ready: Arc<(Mutex, Condvar)>, path: &Path, runs: &[(&[&str], i32 for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { write(&data_socket, arg.as_bytes()).unwrap(); @@ -86,7 +86,7 @@ fn client(ready: Arc<(Mutex, Condvar)>, path: &Path, runs: &[(&[&str], i32 } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); write(&data_socket, b"exit").unwrap(); } @@ -133,7 +133,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { let server = { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - bind_unix(&connection_socket, &addr).unwrap(); + bind(&connection_socket, &addr).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -186,7 +186,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -226,7 +226,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], @@ -255,16 +255,16 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { } /// Similar to `do_test_unix_msg` but uses an unconnected socket and -/// `sendmsg_unix` instead of `sendmsg`. +/// `sendmsg_addr` instead of `sendmsg`. #[cfg(not(any(target_os = "espidf", target_os = "redox", target_os = "wasi")))] fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { use rustix::io::{IoSlice, IoSliceMut}; - use rustix::net::{recvmsg, sendmsg_unix, RecvFlags, ReturnFlags, SendFlags}; + use rustix::net::{recvmsg, sendmsg_addr, RecvFlags, ReturnFlags, SendFlags}; let server = { let runs: &[i32] = &[3, 184, 187, 0]; let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - bind_unix(&data_socket, &addr).unwrap(); + bind(&data_socket, &addr).unwrap(); move || { let mut buffer = [0; BUFFER_SIZE]; @@ -312,7 +312,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); for arg in *args { - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(arg.as_bytes())], @@ -321,7 +321,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { ) .unwrap(); } - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(b"sum")], @@ -332,7 +332,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { } let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(b"exit")], @@ -443,7 +443,7 @@ fn test_unix_msg_with_scm_rights() { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(&path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -522,7 +522,7 @@ fn test_unix_msg_with_scm_rights() { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -565,7 +565,7 @@ fn test_unix_msg_with_scm_rights() { let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space); assert!(cmsg_buffer.push(msg)); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], @@ -740,7 +740,7 @@ fn test_unix_msg_with_combo() { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(&path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -838,7 +838,7 @@ fn test_unix_msg_with_combo() { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -887,7 +887,7 @@ fn test_unix_msg_with_combo() { let msg = SendAncillaryMessage::ScmRights(&we); assert!(cmsg_buffer.push(msg)); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], @@ -940,7 +940,7 @@ fn test_bind_unnamed_address() { assert_eq!(address.abstract_name(), None); assert_eq!(address.path(), None); let sock = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - bind_unix(&sock, &address).unwrap(); + bind(&sock, &address).unwrap(); let address = rustix::net::getsockname(&sock).unwrap(); let address = SocketAddrUnix::try_from(address).unwrap(); diff --git a/tests/net/unix_alloc.rs b/tests/net/unix_alloc.rs index 6580ce5b2..17562fdf1 100644 --- a/tests/net/unix_alloc.rs +++ b/tests/net/unix_alloc.rs @@ -8,7 +8,7 @@ use rustix::fs::{unlinkat, AtFlags, CWD}; use rustix::io::{read, write}; use rustix::net::{ - accept, bind_unix, connect_unix, listen, socket, AddressFamily, SocketAddrUnix, SocketType, + accept, bind, connect, listen, socket, AddressFamily, SocketAddrUnix, SocketType, }; use rustix::path::DecInt; use std::path::Path; @@ -22,7 +22,7 @@ fn server(ready: Arc<(Mutex, Condvar)>, path: &Path) { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); { @@ -69,7 +69,7 @@ fn client(ready: Arc<(Mutex, Condvar)>, path: &Path, runs: &[(&[&str], i32 for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { write(&data_socket, arg.as_bytes()).unwrap(); @@ -84,7 +84,7 @@ fn client(ready: Arc<(Mutex, Condvar)>, path: &Path, runs: &[(&[&str], i32 } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); write(&data_socket, b"exit").unwrap(); } @@ -131,7 +131,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { let server = { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - bind_unix(&connection_socket, &addr).unwrap(); + bind(&connection_socket, &addr).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -184,7 +184,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -223,7 +223,7 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { } let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], @@ -252,16 +252,16 @@ fn do_test_unix_msg(addr: SocketAddrUnix) { } /// Similar to `do_test_unix_msg` but uses an unconnected socket and -/// `sendmsg_unix` instead of `sendmsg`. +/// `sendmsg_addr` instead of `sendmsg`. #[cfg(not(any(target_os = "espidf", target_os = "redox", target_os = "wasi")))] fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { use rustix::io::{IoSlice, IoSliceMut}; - use rustix::net::{recvmsg, sendmsg_unix, RecvFlags, ReturnFlags, SendFlags}; + use rustix::net::{recvmsg, sendmsg_addr, RecvFlags, ReturnFlags, SendFlags}; let server = { let runs: &[i32] = &[3, 184, 187, 0]; let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - bind_unix(&data_socket, &addr).unwrap(); + bind(&data_socket, &addr).unwrap(); move || { let mut buffer = vec![0; BUFFER_SIZE]; @@ -310,7 +310,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); for arg in *args { - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(arg.as_bytes())], @@ -319,7 +319,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { ) .unwrap(); } - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(b"sum")], @@ -330,7 +330,7 @@ fn do_test_unix_msg_unconnected(addr: SocketAddrUnix) { } let data_socket = socket(AddressFamily::UNIX, SocketType::DGRAM, None).unwrap(); - sendmsg_unix( + sendmsg_addr( &data_socket, &addr, &[IoSlice::new(b"exit")], @@ -441,7 +441,7 @@ fn test_unix_msg_with_scm_rights() { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(&path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -520,7 +520,7 @@ fn test_unix_msg_with_scm_rights() { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -563,7 +563,7 @@ fn test_unix_msg_with_scm_rights() { let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space); assert!(cmsg_buffer.push(msg)); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], @@ -681,7 +681,7 @@ fn test_unix_msg_with_combo() { let connection_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); let name = SocketAddrUnix::new(&path).unwrap(); - bind_unix(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); listen(&connection_socket, 1).unwrap(); move || { @@ -779,7 +779,7 @@ fn test_unix_msg_with_combo() { for (args, sum) in runs { let data_socket = socket(AddressFamily::UNIX, SocketType::SEQPACKET, None).unwrap(); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); for arg in *args { sendmsg( @@ -828,7 +828,7 @@ fn test_unix_msg_with_combo() { let msg = SendAncillaryMessage::ScmRights(&we); assert!(cmsg_buffer.push(msg)); - connect_unix(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, &[IoSlice::new(b"exit")], diff --git a/tests/net/v4.rs b/tests/net/v4.rs index b2a2f08ca..428060b36 100644 --- a/tests/net/v4.rs +++ b/tests/net/v4.rs @@ -7,7 +7,7 @@ #[cfg(not(target_os = "redox"))] use rustix::net::ReturnFlags; use rustix::net::{ - accept, bind_v4, connect_v4, getsockname, listen, recv, send, socket, AddressFamily, Ipv4Addr, + accept, bind, connect, getsockname, listen, recv, send, socket, AddressFamily, Ipv4Addr, RecvFlags, SendFlags, SocketAddrV4, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; @@ -19,7 +19,7 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let connection_socket = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0); - bind_v4(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); let who = getsockname(&connection_socket).unwrap(); let who = SocketAddrV4::try_from(who).unwrap(); @@ -55,7 +55,7 @@ fn client(ready: Arc<(Mutex, Condvar)>) { let mut buffer = vec![0; BUFFER_SIZE]; let data_socket = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - connect_v4(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); send(&data_socket, b"hello, world", SendFlags::empty()).unwrap(); @@ -98,7 +98,7 @@ fn test_v4_msg() { let connection_socket = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0); - bind_v4(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); let who = getsockname(&connection_socket).unwrap(); let who = SocketAddrV4::try_from(who).unwrap(); @@ -150,7 +150,7 @@ fn test_v4_msg() { let mut buffer = vec![0; BUFFER_SIZE]; let data_socket = socket(AddressFamily::INET, SocketType::STREAM, None).unwrap(); - connect_v4(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, diff --git a/tests/net/v6.rs b/tests/net/v6.rs index 20611b47b..02824fd90 100644 --- a/tests/net/v6.rs +++ b/tests/net/v6.rs @@ -7,7 +7,7 @@ #[cfg(not(target_os = "redox"))] use rustix::net::ReturnFlags; use rustix::net::{ - accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, + accept, bind, connect, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr, RecvFlags, SendFlags, SocketAddrV6, SocketType, }; use std::sync::{Arc, Condvar, Mutex}; @@ -19,7 +19,7 @@ fn server(ready: Arc<(Mutex, Condvar)>) { let connection_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); - bind_v6(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); let who = getsockname(&connection_socket).unwrap(); let who = SocketAddrV6::try_from(who).unwrap(); @@ -55,7 +55,7 @@ fn client(ready: Arc<(Mutex, Condvar)>) { let mut buffer = vec![0; BUFFER_SIZE]; let data_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - connect_v6(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); send(&data_socket, b"hello, world", SendFlags::empty()).unwrap(); @@ -98,7 +98,7 @@ fn test_v6_msg() { let connection_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0); - bind_v6(&connection_socket, &name).unwrap(); + bind(&connection_socket, &name).unwrap(); let who = getsockname(&connection_socket).unwrap(); let who = SocketAddrV6::try_from(who).unwrap(); @@ -150,7 +150,7 @@ fn test_v6_msg() { let mut buffer = vec![0; BUFFER_SIZE]; let data_socket = socket(AddressFamily::INET6, SocketType::STREAM, None).unwrap(); - connect_v6(&data_socket, &addr).unwrap(); + connect(&data_socket, &addr).unwrap(); sendmsg( &data_socket, From 53b473865a2a1ba86cdd7065afda7df712baeb2b Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sat, 1 Jun 2024 17:04:09 -0600 Subject: [PATCH 5/5] Add support for Netlink socket addresses --- src/backend/libc/net/read_sockaddr.rs | 13 ++++ src/backend/linux_raw/net/read_sockaddr.rs | 11 +++ src/net/socket_addr_any.rs | 6 ++ src/net/types.rs | 83 ++++++++++++++++++++++ tests/net/main.rs | 2 + tests/net/netlink.rs | 64 +++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 tests/net/netlink.rs diff --git a/src/backend/libc/net/read_sockaddr.rs b/src/backend/libc/net/read_sockaddr.rs index 61a7e196c..949954278 100644 --- a/src/backend/libc/net/read_sockaddr.rs +++ b/src/backend/libc/net/read_sockaddr.rs @@ -8,6 +8,8 @@ use crate::backend::c; #[cfg(not(windows))] use crate::ffi::CStr; use crate::io::Errno; +#[cfg(linux_kernel)] +use crate::net::netlink::SocketAddrNetlink; #[cfg(target_os = "linux")] use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp}; use crate::net::{AddressFamily, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; @@ -239,3 +241,14 @@ pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result Result { + if addr.address_family() != AddressFamily::NETLINK { + return Err(Errno::AFNOSUPPORT); + } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups)) +} diff --git a/src/backend/linux_raw/net/read_sockaddr.rs b/src/backend/linux_raw/net/read_sockaddr.rs index 367475d93..fff8ee841 100644 --- a/src/backend/linux_raw/net/read_sockaddr.rs +++ b/src/backend/linux_raw/net/read_sockaddr.rs @@ -4,6 +4,7 @@ use crate::backend::c; use crate::io::Errno; +use crate::net::netlink::SocketAddrNetlink; #[cfg(target_os = "linux")] use crate::net::xdp::{SockaddrXdpFlags, SocketAddrXdp}; use crate::net::{AddressFamily, SocketAddrAny}; @@ -133,3 +134,13 @@ pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result Result { + if addr.address_family() != AddressFamily::NETLINK { + return Err(Errno::AFNOSUPPORT); + } + assert!(addr.len() >= size_of::()); + let decode = unsafe { &*addr.as_ptr().cast::() }; + Ok(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups)) +} diff --git a/src/net/socket_addr_any.rs b/src/net/socket_addr_any.rs index 5fe8be858..dd4053185 100644 --- a/src/net/socket_addr_any.rs +++ b/src/net/socket_addr_any.rs @@ -191,6 +191,12 @@ impl fmt::Debug for SocketAddrAny { return addr.fmt(f); } } + #[cfg(linux_kernel)] + AddressFamily::NETLINK => { + if let Ok(addr) = crate::net::netlink::SocketAddrNetlink::try_from(self.clone()) { + return addr.fmt(f); + } + } _ => {} } diff --git a/src/net/types.rs b/src/net/types.rs index d58931784..567c5e769 100644 --- a/src/net/types.rs +++ b/src/net/types.rs @@ -1003,6 +1003,12 @@ pub mod netlink { use { super::{new_raw_protocol, Protocol}, crate::backend::c, + crate::backend::net::read_sockaddr::read_sockaddr_netlink, + crate::net::{ + addr::{call_with_sockaddr, SocketAddrArg, SocketAddrOpaque}, + SocketAddrAny, + }, + core::mem, }; /// `NETLINK_UNUSED` @@ -1112,6 +1118,83 @@ pub mod netlink { /// `NETLINK_GET_STRICT_CHK` #[cfg(linux_kernel)] pub const GET_STRICT_CHK: Protocol = Protocol(new_raw_protocol(c::NETLINK_GET_STRICT_CHK as _)); + + /// A Netlink socket address. + /// + /// Used to bind to a Netlink socket. + /// + /// Not ABI compatible with `struct sockaddr_nl` + #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] + #[cfg(linux_kernel)] + pub struct SocketAddrNetlink { + /// Port ID + pid: u32, + + /// Multicast groups mask + groups: u32, + } + + #[cfg(linux_kernel)] + impl SocketAddrNetlink { + /// Construct a netlink address + #[inline] + pub fn new(pid: u32, groups: u32) -> Self { + Self { pid, groups } + } + + /// Return port id. + #[inline] + pub fn pid(&self) -> u32 { + self.pid + } + + /// Set port id. + #[inline] + pub fn set_pid(&mut self, pid: u32) { + self.pid = pid; + } + + /// Return multicast groups mask. + #[inline] + pub fn groups(&self) -> u32 { + self.groups + } + + /// Set multicast groups mask. + #[inline] + pub fn set_groups(&mut self, groups: u32) { + self.groups = groups; + } + } + + #[cfg(linux_kernel)] + #[allow(unsafe_code)] + unsafe impl SocketAddrArg for SocketAddrNetlink { + fn with_sockaddr(&self, f: impl FnOnce(*const SocketAddrOpaque, usize) -> R) -> R { + let mut addr: c::sockaddr_nl = unsafe { mem::zeroed() }; + addr.nl_family = c::AF_NETLINK as _; + addr.nl_pid = self.pid; + addr.nl_groups = self.groups; + call_with_sockaddr(&addr, f) + } + } + + #[cfg(linux_kernel)] + impl From for SocketAddrAny { + #[inline] + fn from(from: SocketAddrNetlink) -> Self { + from.as_any() + } + } + + #[cfg(linux_kernel)] + impl TryFrom for SocketAddrNetlink { + type Error = crate::io::Errno; + + fn try_from(addr: SocketAddrAny) -> Result { + read_sockaddr_netlink(&addr) + } + } } /// `ETH_P_*` constants. diff --git a/tests/net/main.rs b/tests/net/main.rs index 01137cc94..e418df001 100644 --- a/tests/net/main.rs +++ b/tests/net/main.rs @@ -10,6 +10,8 @@ mod addr; mod cmsg; mod connect_bind_send; mod dgram; +#[cfg(linux_kernel)] +mod netlink; #[cfg(feature = "event")] mod poll; #[cfg(unix)] diff --git a/tests/net/netlink.rs b/tests/net/netlink.rs new file mode 100644 index 000000000..b31d5e60e --- /dev/null +++ b/tests/net/netlink.rs @@ -0,0 +1,64 @@ +use rustix::net::netlink::{self, SocketAddrNetlink}; +use rustix::net::{ + bind, getsockname, recvfrom, sendto, socket_with, AddressFamily, RecvFlags, SendFlags, + SocketAddrAny, SocketFlags, SocketType, +}; + +#[test] +fn encode_decode() { + let orig = SocketAddrNetlink::new(0x12345678, 0x9abcdef0); + let encoded = SocketAddrAny::from(orig); + let decoded = SocketAddrNetlink::try_from(encoded).unwrap(); + assert_eq!(decoded, orig); +} + +#[test] +fn test_bind_kobject_uevent() { + let server = socket_with( + AddressFamily::NETLINK, + SocketType::RAW, + SocketFlags::CLOEXEC, + Some(netlink::KOBJECT_UEVENT), + ) + .unwrap(); + + bind(&server, &SocketAddrNetlink::new(0, 1)).unwrap(); +} + +#[test] +#[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + ignore = "qemu used in CI does not support NETLINK_USERSOCK" +)] +fn test_usersock() { + let server = socket_with( + AddressFamily::NETLINK, + SocketType::RAW, + SocketFlags::CLOEXEC, + Some(netlink::USERSOCK), + ) + .unwrap(); + + bind(&server, &SocketAddrNetlink::new(0, 0)).unwrap(); + let addr = getsockname(&server).unwrap(); + let addr = SocketAddrNetlink::try_from(addr).unwrap(); + + let client = socket_with( + AddressFamily::NETLINK, + SocketType::RAW, + SocketFlags::CLOEXEC, + Some(netlink::USERSOCK), + ) + .unwrap(); + + let data = b"ABCDEF"; + + sendto(client, data, SendFlags::empty(), &addr).unwrap(); + + let mut buffer = [0u8; 4096]; + let (len, src) = recvfrom(&server, &mut buffer, RecvFlags::empty()).unwrap(); + + assert_eq!(&buffer[..len], data); + let src = SocketAddrNetlink::try_from(src.unwrap()).unwrap(); + assert_eq!(src.groups(), 0); +}