From dd43edc910d494568c6fe409bfc746412cb32feb Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Thu, 20 Mar 2025 11:59:43 +0100 Subject: [PATCH 1/9] Add methods to TCP and UDP sockets to modify hop limit --- library/std/src/lib.rs | 1 + library/std/src/net/tcp.rs | 78 +++++++++++++++++++ library/std/src/net/tcp/tests.rs | 17 ++++ library/std/src/net/udp.rs | 76 ++++++++++++++++++ library/std/src/net/udp/tests.rs | 12 +++ library/std/src/sys/net/connection/sgx.rs | 33 ++++++++ .../std/src/sys/net/connection/socket/mod.rs | 36 +++++++++ .../src/sys/net/connection/socket/windows.rs | 9 ++- .../std/src/sys/net/connection/uefi/mod.rs | 32 ++++++++ .../std/src/sys/net/connection/unsupported.rs | 32 ++++++++ library/std/src/sys/net/connection/wasip1.rs | 32 ++++++++ .../sys/net/connection/xous/tcplistener.rs | 8 ++ .../src/sys/net/connection/xous/tcpstream.rs | 8 ++ .../std/src/sys/net/connection/xous/udp.rs | 16 ++++ .../std/src/sys/pal/windows/c/bindings.txt | 2 + .../std/src/sys/pal/windows/c/windows_sys.rs | 2 + 16 files changed, 390 insertions(+), 4 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index e1061af1e7d6d..03d370e9cb648 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -370,6 +370,7 @@ #![feature(maybe_dangling)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_fill)] +#![feature(ipv6_hop_limit)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index d9090320bd5a6..b0a9b59ad3f35 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -604,6 +604,46 @@ impl TcpStream { self.0.ttl() } + // Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:54321") + /// .expect("Couldn't connect to the server..."); + /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`TcpStream::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:54321") + /// .expect("Couldn't connect to the server..."); + /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + /// Gets the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing @@ -1031,6 +1071,44 @@ impl TcpListener { self.0.ttl() } + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpListener; + /// + /// let listener = TcpListener::bind("127.0.0.1:54321").unwrap(); + /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`TcpListener::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpListener; + /// + /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + #[stable(feature = "net2_mutators", since = "1.9.0")] #[deprecated(since = "1.16.0", note = "this option can only be set before the socket is bound")] #[allow(missing_docs)] diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 45a512cb9b4c7..9b8b28f6cb158 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -894,6 +894,23 @@ fn ttl() { assert_eq!(ttl, t!(stream.ttl())); } +#[test] +#[cfg_attr(target_env = "sgx", ignore)] +fn hop_limit() { + let hlim = 100; + + let addr = next_test_ip6(); + let listener = t!(TcpListener::bind(&addr)); + + t!(listener.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(listener.hop_limit_v6())); + + let stream = t!(TcpStream::connect(&addr)); + + t!(stream.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(stream.hop_limit_v6())); +} + #[test] #[cfg_attr(target_env = "sgx", ignore)] fn set_nonblocking() { diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index cd925b9bdfdf8..4542e630084fc 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -585,6 +585,82 @@ impl UdpSocket { self.0.ttl() } + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`UdpSocket::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + + /// Sets the value for the `IPV6_MULTICAST_HOPS` option on this socket. + /// + /// This value sets the hop limit field for outgoing multicast packets + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_multicast_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_MULTICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`UdpSocket::set_multicast_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); + /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0.multicast_hop_limit_v6() + } + /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. /// /// This function specifies a new multicast group for this socket to join. diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 38d6dab80f64e..84ac9e2cd0c08 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -353,6 +353,18 @@ fn ttl() { assert_eq!(ttl, t!(stream.ttl())); } +#[test] +fn hop_limit() { + let hlim = 100; + + let addr = next_test_ip6(); + + let stream = t!(UdpSocket::bind(&addr)); + + t!(stream.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(stream.hop_limit_v6())); +} + #[test] fn set_nonblocking() { each_ip(&mut |socket, _| { diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs index acebb8c5bd60c..8771a89568da8 100644 --- a/library/std/src/sys/net/connection/sgx.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -9,6 +9,7 @@ use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, u use crate::time::Duration; const DEFAULT_FAKE_TTL: u32 = 64; +const DEFAULT_FAKE_HLIM: u8 = 64; #[derive(Debug, Clone)] pub struct Socket { @@ -243,6 +244,14 @@ impl TcpStream { sgx_ineffective(DEFAULT_FAKE_TTL) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + sgx_ineffective(()) + } + + pub fn hop_limit_v6(&self) -> io::Result { + sgx_ineffective(DEFAULT_FAKE_HLIM) + } + pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -322,6 +331,14 @@ impl TcpListener { sgx_ineffective(DEFAULT_FAKE_TTL) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + sgx_ineffective(()) + } + + pub fn hop_limit_v6(&self) -> io::Result { + sgx_ineffective(DEFAULT_FAKE_HLIM) + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { sgx_ineffective(()) } @@ -461,6 +478,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 769dc66af8ed1..3ee4566ff82f3 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -498,6 +498,15 @@ impl TcpStream { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + } + + pub fn hop_limit_v6(&self) -> io::Result { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + Ok(raw as u8) + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } @@ -626,6 +635,15 @@ impl TcpListener { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + } + + pub fn hop_limit_v6(&self) -> io::Result { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + Ok(raw as u8) + } + pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) } } @@ -850,6 +868,24 @@ impl UdpSocket { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + } + + pub fn hop_limit_v6(&self) -> io::Result { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + Ok(raw as u8) + } + + pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int) + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)?; + Ok(raw as u8) + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs index 075e77bc4457c..7cf4db62b2352 100644 --- a/library/std/src/sys/net/connection/socket/windows.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -29,10 +29,11 @@ pub(super) mod netc { pub use crate::sys::c::{ ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, IPPROTO_IP, IPPROTO_IPV6, - IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, SO_BROADCAST, - SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, SOCK_STREAM, SOCKADDR as sockaddr, - SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, WSAEMSGSIZE as EMSGSIZE, bind, connect, - freeaddrinfo, getpeername, getsockname, getsockopt, listen, setsockopt, + IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, + IPV6_UNICAST_HOPS, IPV6_V6ONLY, SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, + SOCK_STREAM, SOCKADDR as sockaddr, SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, + WSAEMSGSIZE as EMSGSIZE, bind, connect, freeaddrinfo, getpeername, getsockname, getsockopt, + listen, setsockopt, }; #[allow(non_camel_case_types)] diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs index e839b8728de8e..b0ea90e52cbec 100644 --- a/library/std/src/sys/net/connection/uefi/mod.rs +++ b/library/std/src/sys/net/connection/uefi/mod.rs @@ -136,6 +136,14 @@ impl TcpStream { self.inner.ttl() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { unsupported() } @@ -188,6 +196,14 @@ impl TcpListener { self.inner.ttl() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unsupported() } @@ -315,6 +331,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs index 7a4d3a97b8324..df285a4c0987d 100644 --- a/library/std/src/sys/net/connection/unsupported.rs +++ b/library/std/src/sys/net/connection/unsupported.rs @@ -111,6 +111,14 @@ impl TcpStream { self.0 } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } @@ -153,6 +161,14 @@ impl TcpListener { self.0 } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { self.0 } @@ -279,6 +295,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs index d461ea85f9fea..15d7f9a453141 100644 --- a/library/std/src/sys/net/connection/wasip1.rs +++ b/library/std/src/sys/net/connection/wasip1.rs @@ -169,6 +169,14 @@ impl TcpStream { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn take_error(&self) -> io::Result> { unsupported() } @@ -253,6 +261,14 @@ impl TcpListener { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unsupported() } @@ -425,6 +441,22 @@ impl UdpSocket { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn take_error(&self) -> io::Result> { unsupported() } diff --git a/library/std/src/sys/net/connection/xous/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs index f406b4381f29a..e0730b2aac6c8 100644 --- a/library/std/src/sys/net/connection/xous/tcplistener.rs +++ b/library/std/src/sys/net/connection/xous/tcplistener.rs @@ -204,6 +204,14 @@ impl TcpListener { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unimpl!(); } diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 45fe0418a27fa..11cd3f2c008bc 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -403,6 +403,14 @@ impl TcpStream { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn take_error(&self) -> io::Result> { // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. Ok(None) diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index 281639488a015..7b01e715d57af 100644 --- a/library/std/src/sys/net/connection/xous/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs @@ -385,6 +385,14 @@ impl UdpSocket { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn take_error(&self) -> io::Result> { // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. Ok(None) @@ -420,6 +428,14 @@ impl UdpSocket { unimpl!(); } + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { unimpl!(); } diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index a0b2126af9a58..6143dffe3dca0 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2267,7 +2267,9 @@ IPPROTO_UDP IPV6_ADD_MEMBERSHIP IPV6_DROP_MEMBERSHIP IPV6_MREQ +IPV6_MULTICAST_HOPS IPV6_MULTICAST_LOOP +IPV6_UNICAST_HOPS IPV6_V6ONLY IsThreadAFiber LINGER diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 9c6f593e1e108..acf3148ab0154 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -2924,7 +2924,9 @@ impl Default for IPV6_MREQ { unsafe { core::mem::zeroed() } } } +pub const IPV6_MULTICAST_HOPS: i32 = 10i32; pub const IPV6_MULTICAST_LOOP: i32 = 11i32; +pub const IPV6_UNICAST_HOPS: i32 = 4i32; pub const IPV6_V6ONLY: i32 = 27i32; pub const IP_ADD_MEMBERSHIP: i32 = 12i32; pub const IP_DROP_MEMBERSHIP: i32 = 13i32; From 8827e047eee6c110c7c8a235ef14550d54285466 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Thu, 20 Mar 2025 16:03:05 +0100 Subject: [PATCH 2/9] Use IPv6 addresses in hop_limit_v6 docs --- library/std/src/net/tcp.rs | 8 ++++---- library/std/src/net/udp.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index b0a9b59ad3f35..0d4d9ac4bf9fb 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -615,7 +615,7 @@ impl TcpStream { /// #![feature(ipv6_hop_limit)] /// use std::net::TcpStream; /// - /// let stream = TcpStream::connect("127.0.0.1:54321") + /// let stream = TcpStream::connect("[::1]:12345") /// .expect("Couldn't connect to the server..."); /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` @@ -634,7 +634,7 @@ impl TcpStream { /// #![feature(ipv6_hop_limit)] /// use std::net::TcpStream; /// - /// let stream = TcpStream::connect("127.0.0.1:54321") + /// let stream = TcpStream::connect("[::1]:12345") /// .expect("Couldn't connect to the server..."); /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); @@ -1082,7 +1082,7 @@ impl TcpListener { /// #![feature(ipv6_hop_limit)] /// use std::net::TcpListener; /// - /// let listener = TcpListener::bind("127.0.0.1:54321").unwrap(); + /// let listener = TcpListener::bind("[::1]:12345").unwrap(); /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "47727")] @@ -1100,7 +1100,7 @@ impl TcpListener { /// #![feature(ipv6_hop_limit)] /// use std::net::TcpListener; /// - /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// let listener = TcpListener::bind("[::1]:12345").unwrap(); /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); /// ``` diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 4542e630084fc..6c96d05efccd8 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -596,7 +596,7 @@ impl UdpSocket { /// #![feature(ipv6_hop_limit)] /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "47727")] @@ -614,7 +614,7 @@ impl UdpSocket { /// #![feature(ipv6_hop_limit)] /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); /// ``` @@ -634,7 +634,7 @@ impl UdpSocket { /// #![feature(ipv6_hop_limit)] /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "47727")] @@ -652,7 +652,7 @@ impl UdpSocket { /// #![feature(ipv6_hop_limit)] /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:54321").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); /// ``` From 867327f6ee50f4214c6516f1e7dff19b1a6cbe42 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 31 Mar 2025 12:04:44 +0200 Subject: [PATCH 3/9] Update tracking issue to 139166 --- library/std/src/net/tcp.rs | 8 ++++---- library/std/src/net/udp.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 0d4d9ac4bf9fb..5891ce47bf69d 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -619,7 +619,7 @@ impl TcpStream { /// .expect("Couldn't connect to the server..."); /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -639,7 +639,7 @@ impl TcpStream { /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -1085,7 +1085,7 @@ impl TcpListener { /// let listener = TcpListener::bind("[::1]:12345").unwrap(); /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -1104,7 +1104,7 @@ impl TcpListener { /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 6c96d05efccd8..7a84f6d18fff1 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -599,7 +599,7 @@ impl UdpSocket { /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -618,7 +618,7 @@ impl UdpSocket { /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -637,7 +637,7 @@ impl UdpSocket { /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_multicast_hop_limit_v6(limit) } @@ -656,7 +656,7 @@ impl UdpSocket { /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); /// ``` - #[unstable(feature = "ipv6_hop_limit", issue = "47727")] + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] pub fn multicast_hop_limit_v6(&self) -> io::Result { self.0.multicast_hop_limit_v6() } From 636231931522d7636981d03b62141292817ec8c1 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 31 Mar 2025 12:06:28 +0200 Subject: [PATCH 4/9] Update docs according to PR review Co-authored-by: David Tolnay --- library/std/src/net/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 5891ce47bf69d..9df5c5e01fd58 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -604,7 +604,7 @@ impl TcpStream { self.0.ttl() } - // Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. /// /// This value sets the unicast hop limit field that is used in every packet /// sent from this socket. From a258576a5eabd0792937494c1f8ed5d9409f227f Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 16 Apr 2025 12:20:56 +0200 Subject: [PATCH 5/9] Fix unused_variables --- library/std/src/sys/net/connection/unsupported.rs | 8 ++++---- library/std/src/sys/net/connection/xous/tcpstream.rs | 2 +- library/std/src/sys/net/connection/xous/udp.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs index df285a4c0987d..193348a79ae3d 100644 --- a/library/std/src/sys/net/connection/unsupported.rs +++ b/library/std/src/sys/net/connection/unsupported.rs @@ -111,7 +111,7 @@ impl TcpStream { self.0 } - pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { self.0 } @@ -161,7 +161,7 @@ impl TcpListener { self.0 } - pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { self.0 } @@ -295,7 +295,7 @@ impl UdpSocket { self.0 } - pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { self.0 } @@ -303,7 +303,7 @@ impl UdpSocket { self.0 } - pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { self.0 } diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 11cd3f2c008bc..6f8944ba8f18d 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -403,7 +403,7 @@ impl TcpStream { .map(|res| res[0] as _)?) } - pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { unimpl!(); } diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index 7b01e715d57af..e254bfe1a5e45 100644 --- a/library/std/src/sys/net/connection/xous/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs @@ -385,7 +385,7 @@ impl UdpSocket { .map(|res| res[0] as _)?) } - pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { unimpl!(); } From be7a9dd4c8b5ac451c1433d1d08b54e021117a6a Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 24 Mar 2026 12:27:38 +0100 Subject: [PATCH 6/9] fix: add cfg guards on unsupported wasi p2 and p3 targets --- library/std/src/net/tcp.rs | 4 ++++ library/std/src/net/tcp/tests.rs | 1 + library/std/src/net/udp.rs | 4 ++++ library/std/src/net/udp/tests.rs | 1 + library/std/src/sys/net/connection/socket/mod.rs | 8 ++++++++ 5 files changed, 18 insertions(+) diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 9df5c5e01fd58..2af1bc665aa0a 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -620,6 +620,7 @@ impl TcpStream { /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -640,6 +641,7 @@ impl TcpStream { /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -1086,6 +1088,7 @@ impl TcpListener { /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -1105,6 +1108,7 @@ impl TcpListener { /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 9b8b28f6cb158..4db9335a76574 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -896,6 +896,7 @@ fn ttl() { #[test] #[cfg_attr(target_env = "sgx", ignore)] +#[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] fn hop_limit() { let hlim = 100; diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 7a84f6d18fff1..0d8207d9a31ee 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -600,6 +600,7 @@ impl UdpSocket { /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -619,6 +620,7 @@ impl UdpSocket { /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -638,6 +640,7 @@ impl UdpSocket { /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_multicast_hop_limit_v6(limit) } @@ -657,6 +660,7 @@ impl UdpSocket { /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn multicast_hop_limit_v6(&self) -> io::Result { self.0.multicast_hop_limit_v6() } diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 84ac9e2cd0c08..87b4cba5e70da 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -354,6 +354,7 @@ fn ttl() { } #[test] +#[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] fn hop_limit() { let hlim = 100; diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 3ee4566ff82f3..8a469f612d358 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -498,10 +498,12 @@ impl TcpStream { Ok(raw as u32) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; Ok(raw as u8) @@ -635,10 +637,12 @@ impl TcpListener { Ok(raw as u32) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; Ok(raw as u8) @@ -868,19 +872,23 @@ impl UdpSocket { Ok(raw as u32) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; Ok(raw as u8) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int) } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn multicast_hop_limit_v6(&self) -> io::Result { let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)?; Ok(raw as u8) From d7ee60c2a082141b6fe22277c903ad16cb01e8ef Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 24 Mar 2026 13:10:36 +0100 Subject: [PATCH 7/9] fix: tidy PAL and unsafe blocks CI failure --- library/std/src/lib.rs | 2 +- library/std/src/net/tcp.rs | 4 -- library/std/src/net/udp.rs | 4 -- .../std/src/sys/net/connection/socket/mod.rs | 56 ++++++++++++++++--- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 03d370e9cb648..8fd65cf63531c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -365,12 +365,12 @@ #![feature(io_error_uncategorized)] #![feature(io_slice_as_bytes)] #![feature(ip)] +#![feature(ipv6_hop_limit)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(maybe_dangling)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_fill)] -#![feature(ipv6_hop_limit)] #![feature(panic_can_unwind)] #![feature(panic_internals)] #![feature(pin_coerce_unsized_trait)] diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 2af1bc665aa0a..9df5c5e01fd58 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -620,7 +620,6 @@ impl TcpStream { /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -641,7 +640,6 @@ impl TcpStream { /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -1088,7 +1086,6 @@ impl TcpListener { /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -1108,7 +1105,6 @@ impl TcpListener { /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 0d8207d9a31ee..7a84f6d18fff1 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -600,7 +600,6 @@ impl UdpSocket { /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_hop_limit_v6(limit) } @@ -620,7 +619,6 @@ impl UdpSocket { /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { self.0.hop_limit_v6() } @@ -640,7 +638,6 @@ impl UdpSocket { /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { self.0.set_multicast_hop_limit_v6(limit) } @@ -660,7 +657,6 @@ impl UdpSocket { /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); /// ``` #[unstable(feature = "ipv6_hop_limit", issue = "139166")] - #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn multicast_hop_limit_v6(&self) -> io::Result { self.0.multicast_hop_limit_v6() } diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 8a469f612d358..ad2fe5cf1a7f3 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -500,15 +500,25 @@ impl TcpStream { #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + } + + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) } #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; Ok(raw as u8) } + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn hop_limit_v6(&self) -> io::Result { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } @@ -639,15 +649,25 @@ impl TcpListener { #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + } + + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) } #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; Ok(raw as u8) } + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn hop_limit_v6(&self) -> io::Result { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) } } @@ -874,26 +894,46 @@ impl UdpSocket { #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) } + } + + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) } #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn hop_limit_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?; + let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; Ok(raw as u8) } + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn hop_limit_v6(&self) -> io::Result { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int) + unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int) } + } + + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) } #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn multicast_hop_limit_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)?; + let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? }; Ok(raw as u8) } + #[cfg(all(target_os = "wasi", any(target_env = "p2", target_env = "p3")))] + pub fn multicast_hop_limit_v6(&self) -> io::Result { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } From b0fa536976a80f0a8c254a9e0cd3c3fe192d5a2e Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Tue, 24 Mar 2026 15:02:06 +0100 Subject: [PATCH 8/9] fix: tidy CI --- library/std/src/sys/net/connection/socket/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index ad2fe5cf1a7f3..2d0de23315b3b 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -925,7 +925,8 @@ impl UdpSocket { #[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] pub fn multicast_hop_limit_v6(&self) -> io::Result { - let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? }; + let raw: c_int = + unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? }; Ok(raw as u8) } From 61fbce53b237a2f098eca4c13965eeb432623f81 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Thu, 6 Aug 2026 17:34:10 +0200 Subject: [PATCH 9/9] fix: port tests to new TCP testing framework --- library/std/src/net/tcp/tests.rs | 5 ++--- library/std/src/net/udp/tests.rs | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 4db9335a76574..58de3d478caa0 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -900,13 +900,12 @@ fn ttl() { fn hop_limit() { let hlim = 100; - let addr = next_test_ip6(); - let listener = t!(TcpListener::bind(&addr)); + let listener = t!(TcpListener::bind(LOCALHOST_IP6)); t!(listener.set_hop_limit_v6(hlim)); assert_eq!(hlim, t!(listener.hop_limit_v6())); - let stream = t!(TcpStream::connect(&addr)); + let stream = t!(TcpStream::connect(t!(listener.local_addr()))); t!(stream.set_hop_limit_v6(hlim)); assert_eq!(hlim, t!(stream.hop_limit_v6())); diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 87b4cba5e70da..89ec91122c5fb 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -358,9 +358,7 @@ fn ttl() { fn hop_limit() { let hlim = 100; - let addr = next_test_ip6(); - - let stream = t!(UdpSocket::bind(&addr)); + let stream = t!(UdpSocket::bind(LOCALHOST_IP6)); t!(stream.set_hop_limit_v6(hlim)); assert_eq!(hlim, t!(stream.hop_limit_v6()));