Rollup merge of #136699 - joboet:netaddr_from_inner, r=cuviper

std: replace the `FromInner` implementation for addresses with private conversion functions

Having these implementation available crate-wide means that platforms not using sockets for their networking code have to stub out the libc definitions required to support them. This PR moves the conversions to private helper functions that are only available where actually needed.

I also fixed the signature of the function converting from a C socket address to a Rust one: taking a reference to a `sockaddr_storage` resulted in unsound usage inside  `LookupHost::next`, which could create a reference to a structure smaller than `sockaddr_storage`. Thus I've replaced the argument type with a pointer and made the function `unsafe`.
This commit is contained in:
Jacob Pratt 2025-02-12 20:09:59 -05:00 committed by GitHub
commit 4ce473ccba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 155 additions and 348 deletions

View File

@ -8,32 +8,3 @@ pub use core::net::IpAddr;
pub use core::net::Ipv6MulticastScope; pub use core::net::Ipv6MulticastScope;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::net::{Ipv4Addr, Ipv6Addr}; pub use core::net::{Ipv4Addr, Ipv6Addr};
use crate::sys::net::netc as c;
use crate::sys_common::{FromInner, IntoInner};
impl IntoInner<c::in_addr> for Ipv4Addr {
#[inline]
fn into_inner(self) -> c::in_addr {
// `s_addr` is stored as BE on all machines and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) }
}
}
impl FromInner<c::in_addr> for Ipv4Addr {
fn from_inner(addr: c::in_addr) -> Ipv4Addr {
Ipv4Addr::from(addr.s_addr.to_ne_bytes())
}
}
impl IntoInner<c::in6_addr> for Ipv6Addr {
fn into_inner(self) -> c::in6_addr {
c::in6_addr { s6_addr: self.octets() }
}
}
impl FromInner<c::in6_addr> for Ipv6Addr {
#[inline]
fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
Ipv6Addr::from(addr.s6_addr)
}
}

View File

@ -6,50 +6,8 @@ mod tests;
pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::sys::net::{LookupHost, netc as c}; use crate::sys::net::LookupHost;
use crate::sys_common::{FromInner, IntoInner}; use crate::{io, iter, option, slice, vec};
use crate::{io, iter, mem, option, slice, vec};
impl FromInner<c::sockaddr_in> for SocketAddrV4 {
fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port))
}
}
impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
SocketAddrV6::new(
Ipv6Addr::from_inner(addr.sin6_addr),
u16::from_be(addr.sin6_port),
addr.sin6_flowinfo,
addr.sin6_scope_id,
)
}
}
impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
fn into_inner(self) -> c::sockaddr_in {
c::sockaddr_in {
sin_family: c::AF_INET as c::sa_family_t,
sin_port: self.port().to_be(),
sin_addr: self.ip().into_inner(),
..unsafe { mem::zeroed() }
}
}
}
impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
fn into_inner(self) -> c::sockaddr_in6 {
c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t,
sin6_port: self.port().to_be(),
sin6_addr: self.ip().into_inner(),
sin6_flowinfo: self.flowinfo(),
sin6_scope_id: self.scope_id(),
..unsafe { mem::zeroed() }
}
}
}
/// A trait for objects which can be converted or resolved to one or more /// A trait for objects which can be converted or resolved to one or more
/// [`SocketAddr`] values. /// [`SocketAddr`] values.

View File

@ -122,7 +122,7 @@ impl BorrowedFd<'_> {
/// Creates a new `OwnedFd` instance that shares the same underlying file /// Creates a new `OwnedFd` instance that shares the same underlying file
/// description as the existing `BorrowedFd` instance. /// description as the existing `BorrowedFd` instance.
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> { pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?; let fd = sys::net::cvt(unsafe { crate::sys::abi::sockets::dup(self.as_raw_fd()) })?;
Ok(unsafe { OwnedFd::from_raw_fd(fd) }) Ok(unsafe { OwnedFd::from_raw_fd(fd) })
} }
} }
@ -168,7 +168,7 @@ impl FromRawFd for OwnedFd {
impl Drop for OwnedFd { impl Drop for OwnedFd {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
unsafe { sys::net::netc::close(self.fd.as_inner()) }; unsafe { crate::sys::abi::sockets::close(self.fd.as_inner()) };
} }
} }

View File

@ -499,38 +499,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
LookupHost::new(format!("{host}:{port}")) LookupHost::new(format!("{host}:{port}"))
} }
} }
#[allow(bad_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -3,9 +3,9 @@ mod tests;
use crate::ffi::{c_int, c_void}; use crate::ffi::{c_int, c_void};
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::sys::common::small_c_string::run_with_cstr; use crate::sys::common::small_c_string::run_with_cstr;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner};
use crate::time::Duration; use crate::time::Duration;
use crate::{cmp, fmt, mem, ptr}; use crate::{cmp, fmt, mem, ptr};
@ -79,6 +79,111 @@ cfg_if::cfg_if! {
} }
} }
////////////////////////////////////////////////////////////////////////////////
// address conversions
////////////////////////////////////////////////////////////////////////////////
fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr {
// `s_addr` is stored as BE on all machines and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) }
}
fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr {
c::in6_addr { s6_addr: addr.octets() }
}
fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr {
Ipv4Addr::from(addr.s_addr.to_ne_bytes())
}
fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr {
Ipv6Addr::from(addr.s6_addr)
}
fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in {
c::sockaddr_in {
sin_family: c::AF_INET as c::sa_family_t,
sin_port: addr.port().to_be(),
sin_addr: ip_v4_addr_to_c(addr.ip()),
..unsafe { mem::zeroed() }
}
}
fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 {
c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t,
sin6_port: addr.port().to_be(),
sin6_addr: ip_v6_addr_to_c(addr.ip()),
sin6_flowinfo: addr.flowinfo(),
sin6_scope_id: addr.scope_id(),
..unsafe { mem::zeroed() }
}
}
fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 {
SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port))
}
fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 {
SocketAddrV6::new(
ip_v6_addr_from_c(addr.sin6_addr),
u16::from_be(addr.sin6_port),
addr.sin6_flowinfo,
addr.sin6_scope_id,
)
}
/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
#[repr(C)]
union SocketAddrCRepr {
v4: c::sockaddr_in,
v6: c::sockaddr_in6,
}
impl SocketAddrCRepr {
fn as_ptr(&self) -> *const c::sockaddr {
self as *const _ as *const c::sockaddr
}
}
fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
match addr {
SocketAddr::V4(a) => {
let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) };
(sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
}
SocketAddr::V6(a) => {
let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) };
(sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
}
}
}
unsafe fn socket_addr_from_c(
storage: *const c::sockaddr_storage,
len: usize,
) -> io::Result<SocketAddr> {
match (*storage).ss_family as c_int {
c::AF_INET => {
assert!(len >= mem::size_of::<c::sockaddr_in>());
Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
*(storage as *const _ as *const c::sockaddr_in)
})))
}
c::AF_INET6 => {
assert!(len >= mem::size_of::<c::sockaddr_in6>());
Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
*(storage as *const _ as *const c::sockaddr_in6)
})))
}
_ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// sockaddr and misc bindings // sockaddr and misc bindings
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -124,25 +229,7 @@ where
let mut storage: c::sockaddr_storage = mem::zeroed(); let mut storage: c::sockaddr_storage = mem::zeroed();
let mut len = mem::size_of_val(&storage) as c::socklen_t; let mut len = mem::size_of_val(&storage) as c::socklen_t;
cvt(f((&raw mut storage) as *mut _, &mut len))?; cvt(f((&raw mut storage) as *mut _, &mut len))?;
sockaddr_to_addr(&storage, len as usize) socket_addr_from_c(&storage, len as usize)
}
}
pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
match storage.ss_family as c_int {
c::AF_INET => {
assert!(len >= mem::size_of::<c::sockaddr_in>());
Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
*(storage as *const _ as *const c::sockaddr_in)
})))
}
c::AF_INET6 => {
assert!(len >= mem::size_of::<c::sockaddr_in6>());
Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
*(storage as *const _ as *const c::sockaddr_in6)
})))
}
_ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
} }
} }
@ -179,7 +266,7 @@ impl Iterator for LookupHost {
unsafe { unsafe {
let cur = self.cur.as_ref()?; let cur = self.cur.as_ref()?;
self.cur = cur.ai_next; self.cur = cur.ai_next;
match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) { match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
Ok(addr) => return Some(addr), Ok(addr) => return Some(addr),
Err(_) => continue, Err(_) => continue,
} }
@ -432,7 +519,7 @@ impl TcpListener {
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
// Bind our new socket // Bind our new socket
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
cfg_if::cfg_if! { cfg_if::cfg_if! {
@ -473,7 +560,7 @@ impl TcpListener {
let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of_val(&storage) as c::socklen_t; let mut len = mem::size_of_val(&storage) as c::socklen_t;
let sock = self.inner.accept((&raw mut storage) as *mut _, &mut len)?; let sock = self.inner.accept((&raw mut storage) as *mut _, &mut len)?;
let addr = sockaddr_to_addr(&storage, len as usize)?; let addr = unsafe { socket_addr_from_c(&storage, len as usize)? };
Ok((TcpStream { inner: sock }, addr)) Ok((TcpStream { inner: sock }, addr))
} }
@ -542,7 +629,7 @@ impl UdpSocket {
init(); init();
let sock = Socket::new(addr, c::SOCK_DGRAM)?; let sock = Socket::new(addr, c::SOCK_DGRAM)?;
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
Ok(UdpSocket { inner: sock }) Ok(UdpSocket { inner: sock })
} }
@ -574,7 +661,7 @@ impl UdpSocket {
pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
let (dst, dstlen) = dst.into_inner(); let (dst, dstlen) = socket_addr_to_c(dst);
let ret = cvt(unsafe { let ret = cvt(unsafe {
c::sendto( c::sendto(
self.inner.as_raw(), self.inner.as_raw(),
@ -656,15 +743,15 @@ impl UdpSocket {
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = c::ip_mreq { let mreq = c::ip_mreq {
imr_multiaddr: multiaddr.into_inner(), imr_multiaddr: ip_v4_addr_to_c(multiaddr),
imr_interface: interface.into_inner(), imr_interface: ip_v4_addr_to_c(interface),
}; };
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
} }
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = c::ipv6_mreq { let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: multiaddr.into_inner(), ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface), ipv6mr_interface: to_ipv6mr_interface(interface),
}; };
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
@ -672,15 +759,15 @@ impl UdpSocket {
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = c::ip_mreq { let mreq = c::ip_mreq {
imr_multiaddr: multiaddr.into_inner(), imr_multiaddr: ip_v4_addr_to_c(multiaddr),
imr_interface: interface.into_inner(), imr_interface: ip_v4_addr_to_c(interface),
}; };
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
} }
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = c::ipv6_mreq { let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: multiaddr.into_inner(), ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface), ipv6mr_interface: to_ipv6mr_interface(interface),
}; };
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
@ -720,7 +807,7 @@ impl UdpSocket {
} }
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
let (addr, len) = addr?.into_inner(); let (addr, len) = socket_addr_to_c(addr?);
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop) cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
} }
} }
@ -743,38 +830,3 @@ impl fmt::Debug for UdpSocket {
res.field(name, &self.inner.as_raw()).finish() res.field(name, &self.inner.as_raw()).finish()
} }
} }
////////////////////////////////////////////////////////////////////////////////
// Converting SocketAddr to libc representation
////////////////////////////////////////////////////////////////////////////////
/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
/// SocketAddr* types into their system representation. The benefit of this specific
/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
#[repr(C)]
pub(crate) union SocketAddrCRepr {
v4: c::sockaddr_in,
v6: c::sockaddr_in6,
}
impl SocketAddrCRepr {
pub fn as_ptr(&self) -> *const c::sockaddr {
self as *const _ as *const c::sockaddr
}
}
impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr {
fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) {
match *self {
SocketAddr::V4(ref a) => {
let sockaddr = SocketAddrCRepr { v4: a.into_inner() };
(sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
}
SocketAddr::V6(ref a) => {
let sockaddr = SocketAddrCRepr { v6: a.into_inner() };
(sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
}
}
}
}

View File

@ -2,13 +2,13 @@
use core::ffi::c_int; use core::ffi::c_int;
pub(crate) use hermit_abi as netc; pub(super) use hermit_abi as netc;
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr}; use crate::net::{Shutdown, SocketAddr};
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
use crate::sys::fd::FileDesc; use crate::sys::fd::FileDesc;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys::time::Instant; use crate::sys::time::Instant;
pub use crate::sys::{cvt, cvt_r}; pub use crate::sys::{cvt, cvt_r};
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
@ -55,7 +55,7 @@ impl Socket {
} }
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(()) Ok(())
} }
@ -63,7 +63,7 @@ impl Socket {
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?; self.set_nonblocking(true)?;
let r = unsafe { let r = unsafe {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len)) cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len))
}; };
self.set_nonblocking(false)?; self.set_nonblocking(false)?;
@ -195,7 +195,7 @@ impl Socket {
&mut addrlen, &mut addrlen,
) )
})?; })?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} }
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -1,17 +1,17 @@
use libc::{c_int, c_void, size_t}; use libc::{c_int, c_void, size_t};
use self::netc::{MSG_PEEK, sockaddr, socklen_t}; use self::netc::{MSG_PEEK, sockaddr, socklen_t};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::ffi::CStr; use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr}; use crate::net::{Shutdown, SocketAddr};
use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}; use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
use crate::sys::abi; use crate::sys::abi;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys_common::{FromInner, IntoInner}; use crate::sys_common::{FromInner, IntoInner};
use crate::time::Duration; use crate::time::Duration;
use crate::{cmp, mem, ptr, str}; use crate::{cmp, mem, ptr, str};
pub mod netc { pub(super) mod netc {
pub use crate::sys::abi::sockets::*; pub use crate::sys::abi::sockets::*;
} }
@ -131,7 +131,7 @@ impl Socket {
} }
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(()) Ok(())
} }
@ -256,7 +256,7 @@ impl Socket {
&mut addrlen, &mut addrlen,
) )
})?; })?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} }
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -5,7 +5,7 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr}; use crate::net::{Shutdown, SocketAddr};
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc; use crate::sys::fd::FileDesc;
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys::net::{getsockopt, setsockopt};
use crate::sys::pal::IsMinusOne; use crate::sys::pal::IsMinusOne;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant}; use crate::time::{Duration, Instant};
@ -19,8 +19,9 @@ cfg_if::cfg_if! {
} }
} }
pub(crate) use libc as netc; pub(super) use libc as netc;
use super::{socket_addr_from_c, socket_addr_to_c};
pub use crate::sys::{cvt, cvt_r}; pub use crate::sys::{cvt, cvt_r};
#[expect(non_camel_case_types)] #[expect(non_camel_case_types)]
@ -150,7 +151,7 @@ impl Socket {
} }
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
loop { loop {
let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) }; let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) };
if result.is_minus_one() { if result.is_minus_one() {
@ -168,7 +169,7 @@ impl Socket {
pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?; self.set_nonblocking(true)?;
let r = unsafe { let r = unsafe {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len)) cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len))
}; };
self.set_nonblocking(false)?; self.set_nonblocking(false)?;
@ -334,7 +335,7 @@ impl Socket {
&mut addrlen, &mut addrlen,
) )
})?; })?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} }
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -1,19 +1,18 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
pub(super) use libc as netc;
use libc::{c_int, c_void, size_t}; use libc::{c_int, c_void, size_t};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::ffi::CStr; use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr}; use crate::net::{Shutdown, SocketAddr};
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys::unsupported; use crate::sys::unsupported;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant}; use crate::time::{Duration, Instant};
use crate::{cmp, mem, str}; use crate::{cmp, mem, str};
pub extern crate libc as netc;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type wrlen_t = size_t; pub type wrlen_t = size_t;
@ -89,7 +88,7 @@ impl Socket {
} }
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?;
Ok(()) Ok(())
} }
@ -224,7 +223,7 @@ impl Socket {
&mut addrlen, &mut addrlen,
) )
})?; })?;
Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} }
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {

View File

@ -2,6 +2,7 @@
use core::ffi::{c_int, c_long, c_ulong, c_ushort}; use core::ffi::{c_int, c_long, c_ulong, c_ushort};
use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c};
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read};
use crate::net::{Shutdown, SocketAddr}; use crate::net::{Shutdown, SocketAddr};
use crate::os::windows::io::{ use crate::os::windows::io::{
@ -16,7 +17,7 @@ use crate::{cmp, mem, ptr, sys};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type wrlen_t = i32; pub type wrlen_t = i32;
pub mod netc { pub(super) mod netc {
//! BSD socket compatibility shim //! BSD socket compatibility shim
//! //!
//! Some Windows API types are not quite what's expected by our cross-platform //! Some Windows API types are not quite what's expected by our cross-platform
@ -225,7 +226,7 @@ impl Socket {
} }
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
let (addr, len) = addr.into_inner(); let (addr, len) = socket_addr_to_c(addr);
let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) };
cvt(result).map(drop) cvt(result).map(drop)
} }
@ -401,12 +402,12 @@ impl Socket {
let error = unsafe { c::WSAGetLastError() }; let error = unsafe { c::WSAGetLastError() };
if error == c::WSAESHUTDOWN { if error == c::WSAESHUTDOWN {
Ok((0, super::sockaddr_to_addr(&storage, addrlen as usize)?)) Ok((0, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
} else { } else {
Err(io::Error::from_raw_os_error(error)) Err(io::Error::from_raw_os_error(error))
} }
} }
_ => Ok((result as usize, super::sockaddr_to_addr(&storage, addrlen as usize)?)), _ => Ok((result as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })),
} }
} }
@ -451,11 +452,11 @@ impl Socket {
} }
None => 0, None => 0,
}; };
super::setsockopt(self, c::SOL_SOCKET, kind, timeout) setsockopt(self, c::SOL_SOCKET, kind, timeout)
} }
pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> { pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> {
let raw: u32 = super::getsockopt(self, c::SOL_SOCKET, kind)?; let raw: u32 = getsockopt(self, c::SOL_SOCKET, kind)?;
if raw == 0 { if raw == 0 {
Ok(None) Ok(None)
} else { } else {
@ -488,26 +489,26 @@ impl Socket {
l_linger: linger.unwrap_or_default().as_secs() as c_ushort, l_linger: linger.unwrap_or_default().as_secs() as c_ushort,
}; };
super::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger) setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
} }
pub fn linger(&self) -> io::Result<Option<Duration>> { pub fn linger(&self) -> io::Result<Option<Duration>> {
let val: c::LINGER = super::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?; let val: c::LINGER = getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
} }
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
super::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL)
} }
pub fn nodelay(&self) -> io::Result<bool> { pub fn nodelay(&self) -> io::Result<bool> {
let raw: c::BOOL = super::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; let raw: c::BOOL = getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?;
Ok(raw != 0) Ok(raw != 0)
} }
pub fn take_error(&self) -> io::Result<Option<io::Error>> { pub fn take_error(&self) -> io::Result<Option<io::Error>> {
let raw: c_int = super::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?; let raw: c_int = getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?;
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
} }

View File

@ -332,38 +332,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported() unsupported()
} }
} }
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -332,38 +332,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported() unsupported()
} }
} }
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -505,38 +505,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
unsupported() unsupported()
} }
} }
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}

View File

@ -46,38 +46,3 @@ pub struct GetAddress {
} }
pub use dns::LookupHost; pub use dns::LookupHost;
#[allow(nonstandard_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
#[allow(dead_code)]
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
#[allow(dead_code)]
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
}