Skip to content

Commit 6b5fa05

Browse files
Auto merge of #138744 - Mallets:set_ipv6_sock_hop_limit, r=<try>
Add methods to TCP and UDP sockets to modify hop limit (refresh of #94678)
2 parents 033c0a4 + 6657c75 commit 6b5fa05

File tree

16 files changed

+389
-4
lines changed

16 files changed

+389
-4
lines changed

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@
354354
#![feature(hashmap_internals)]
355355
#![feature(hint_must_use)]
356356
#![feature(ip)]
357+
#![feature(ipv6_hop_limit)]
357358
#![feature(lazy_get)]
358359
#![feature(maybe_uninit_slice)]
359360
#![feature(maybe_uninit_write_slice)]

library/std/src/net/tcp.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,46 @@ impl TcpStream {
554554
self.0.ttl()
555555
}
556556

557+
/// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
558+
///
559+
/// This value sets the unicast hop limit field that is used in every packet
560+
/// sent from this socket.
561+
///
562+
/// # Examples
563+
///
564+
/// ```no_run
565+
/// #![feature(ipv6_hop_limit)]
566+
/// use std::net::TcpStream;
567+
///
568+
/// let stream = TcpStream::connect("[::1]:12345")
569+
/// .expect("Couldn't connect to the server...");
570+
/// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
571+
/// ```
572+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
573+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
574+
self.0.set_hop_limit_v6(limit)
575+
}
576+
577+
/// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket.
578+
///
579+
/// For more information about this option, see [`TcpStream::set_hop_limit_v6`].
580+
///
581+
/// # Examples
582+
///
583+
/// ```no_run
584+
/// #![feature(ipv6_hop_limit)]
585+
/// use std::net::TcpStream;
586+
///
587+
/// let stream = TcpStream::connect("[::1]:12345")
588+
/// .expect("Couldn't connect to the server...");
589+
/// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
590+
/// assert_eq!(stream.hop_limit_v6().unwrap(), 88);
591+
/// ```
592+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
593+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
594+
self.0.hop_limit_v6()
595+
}
596+
557597
/// Gets the value of the `SO_ERROR` option on this socket.
558598
///
559599
/// This will retrieve the stored error in the underlying socket, clearing
@@ -948,6 +988,44 @@ impl TcpListener {
948988
self.0.ttl()
949989
}
950990

991+
/// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
992+
///
993+
/// This value sets the unicast hop limit field that is used in every packet
994+
/// sent from this socket.
995+
///
996+
/// # Examples
997+
///
998+
/// ```no_run
999+
/// #![feature(ipv6_hop_limit)]
1000+
/// use std::net::TcpListener;
1001+
///
1002+
/// let listener = TcpListener::bind("[::1]:12345").unwrap();
1003+
/// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
1004+
/// ```
1005+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
1006+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
1007+
self.0.set_hop_limit_v6(limit)
1008+
}
1009+
1010+
/// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket.
1011+
///
1012+
/// For more information about this option, see [`TcpListener::set_hop_limit_v6`].
1013+
///
1014+
/// # Examples
1015+
///
1016+
/// ```no_run
1017+
/// #![feature(ipv6_hop_limit)]
1018+
/// use std::net::TcpListener;
1019+
///
1020+
/// let listener = TcpListener::bind("[::1]:12345").unwrap();
1021+
/// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
1022+
/// assert_eq!(listener.hop_limit_v6().unwrap(), 88);
1023+
/// ```
1024+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
1025+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
1026+
self.0.hop_limit_v6()
1027+
}
1028+
9511029
#[stable(feature = "net2_mutators", since = "1.9.0")]
9521030
#[deprecated(since = "1.16.0", note = "this option can only be set before the socket is bound")]
9531031
#[allow(missing_docs)]

library/std/src/net/tcp/tests.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,23 @@ fn ttl() {
875875
assert_eq!(ttl, t!(stream.ttl()));
876876
}
877877

878+
#[test]
879+
#[cfg_attr(target_env = "sgx", ignore)]
880+
fn hop_limit() {
881+
let hlim = 100;
882+
883+
let addr = next_test_ip6();
884+
let listener = t!(TcpListener::bind(&addr));
885+
886+
t!(listener.set_hop_limit_v6(hlim));
887+
assert_eq!(hlim, t!(listener.hop_limit_v6()));
888+
889+
let stream = t!(TcpStream::connect(&addr));
890+
891+
t!(stream.set_hop_limit_v6(hlim));
892+
assert_eq!(hlim, t!(stream.hop_limit_v6()));
893+
}
894+
878895
#[test]
879896
#[cfg_attr(target_env = "sgx", ignore)]
880897
fn set_nonblocking() {

library/std/src/net/udp.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,82 @@ impl UdpSocket {
582582
self.0.ttl()
583583
}
584584

585+
/// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
586+
///
587+
/// This value sets the unicast hop limit field that is used in every packet
588+
/// sent from this socket.
589+
///
590+
/// # Examples
591+
///
592+
/// ```no_run
593+
/// #![feature(ipv6_hop_limit)]
594+
/// use std::net::UdpSocket;
595+
///
596+
/// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address");
597+
/// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
598+
/// ```
599+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
600+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
601+
self.0.set_hop_limit_v6(limit)
602+
}
603+
604+
/// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket.
605+
///
606+
/// For more information about this option, see [`UdpSocket::set_hop_limit_v6`].
607+
///
608+
/// # Examples
609+
///
610+
/// ```no_run
611+
/// #![feature(ipv6_hop_limit)]
612+
/// use std::net::UdpSocket;
613+
///
614+
/// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address");
615+
/// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed");
616+
/// assert_eq!(socket.hop_limit_v6().unwrap(), 88);
617+
/// ```
618+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
619+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
620+
self.0.hop_limit_v6()
621+
}
622+
623+
/// Sets the value for the `IPV6_MULTICAST_HOPS` option on this socket.
624+
///
625+
/// This value sets the hop limit field for outgoing multicast packets
626+
/// sent from this socket.
627+
///
628+
/// # Examples
629+
///
630+
/// ```no_run
631+
/// #![feature(ipv6_hop_limit)]
632+
/// use std::net::UdpSocket;
633+
///
634+
/// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address");
635+
/// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed");
636+
/// ```
637+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
638+
pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
639+
self.0.set_multicast_hop_limit_v6(limit)
640+
}
641+
642+
/// Gets the value of the `IPV6_MULTICAST_HOPS` option on this socket.
643+
///
644+
/// For more information about this option, see [`UdpSocket::set_multicast_hop_limit_v6`].
645+
///
646+
/// # Examples
647+
///
648+
/// ```no_run
649+
/// #![feature(ipv6_hop_limit)]
650+
/// use std::net::UdpSocket;
651+
///
652+
/// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address");
653+
/// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed");
654+
/// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88);
655+
/// ```
656+
#[unstable(feature = "ipv6_hop_limit", issue = "139166")]
657+
pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
658+
self.0.multicast_hop_limit_v6()
659+
}
660+
585661
/// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
586662
///
587663
/// This function specifies a new multicast group for this socket to join.

library/std/src/net/udp/tests.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,18 @@ fn ttl() {
357357
assert_eq!(ttl, t!(stream.ttl()));
358358
}
359359

360+
#[test]
361+
fn hop_limit() {
362+
let hlim = 100;
363+
364+
let addr = next_test_ip6();
365+
366+
let stream = t!(UdpSocket::bind(&addr));
367+
368+
t!(stream.set_hop_limit_v6(hlim));
369+
assert_eq!(hlim, t!(stream.hop_limit_v6()));
370+
}
371+
360372
#[test]
361373
fn set_nonblocking() {
362374
each_ip(&mut |addr, _| {

library/std/src/sys/net/connection/sgx.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::time::Duration;
88
use crate::{error, fmt};
99

1010
const DEFAULT_FAKE_TTL: u32 = 64;
11+
const DEFAULT_FAKE_HLIM: u8 = 64;
1112

1213
#[derive(Debug, Clone)]
1314
pub struct Socket {
@@ -199,6 +200,14 @@ impl TcpStream {
199200
sgx_ineffective(DEFAULT_FAKE_TTL)
200201
}
201202

203+
pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> {
204+
sgx_ineffective(())
205+
}
206+
207+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
208+
sgx_ineffective(DEFAULT_FAKE_HLIM)
209+
}
210+
202211
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
203212
Ok(None)
204213
}
@@ -277,6 +286,14 @@ impl TcpListener {
277286
sgx_ineffective(DEFAULT_FAKE_TTL)
278287
}
279288

289+
pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> {
290+
sgx_ineffective(())
291+
}
292+
293+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
294+
sgx_ineffective(DEFAULT_FAKE_HLIM)
295+
}
296+
280297
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
281298
sgx_ineffective(())
282299
}
@@ -416,6 +433,22 @@ impl UdpSocket {
416433
self.0
417434
}
418435

436+
pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> {
437+
self.0
438+
}
439+
440+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
441+
self.0
442+
}
443+
444+
pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> {
445+
self.0
446+
}
447+
448+
pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
449+
self.0
450+
}
451+
419452
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
420453
self.0
421454
}

library/std/src/sys/net/connection/socket.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,15 @@ impl TcpStream {
464464
Ok(raw as u32)
465465
}
466466

467+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
468+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
469+
}
470+
471+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
472+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
473+
Ok(raw as u8)
474+
}
475+
467476
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
468477
self.inner.take_error()
469478
}
@@ -593,6 +602,15 @@ impl TcpListener {
593602
Ok(raw as u32)
594603
}
595604

605+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
606+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
607+
}
608+
609+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
610+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
611+
Ok(raw as u8)
612+
}
613+
596614
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
597615
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
598616
}
@@ -798,6 +816,24 @@ impl UdpSocket {
798816
Ok(raw as u32)
799817
}
800818

819+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
820+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
821+
}
822+
823+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
824+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
825+
Ok(raw as u8)
826+
}
827+
828+
pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
829+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int)
830+
}
831+
832+
pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
833+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)?;
834+
Ok(raw as u8)
835+
}
836+
801837
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
802838
self.inner.take_error()
803839
}

library/std/src/sys/net/connection/socket/windows.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ pub(super) mod netc {
3131
pub use crate::sys::c::{
3232
ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IP_ADD_MEMBERSHIP,
3333
IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, IPPROTO_IP, IPPROTO_IPV6,
34-
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, SO_BROADCAST,
35-
SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, SOCK_STREAM, SOCKADDR as sockaddr,
36-
SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, bind, connect, freeaddrinfo, getpeername,
37-
getsockname, getsockopt, listen, setsockopt,
34+
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP,
35+
IPV6_UNICAST_HOPS, IPV6_V6ONLY, SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM,
36+
SOCK_STREAM, SOCKADDR as sockaddr, SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, bind,
37+
connect, freeaddrinfo, getpeername, getsockname, getsockopt, listen, setsockopt,
3838
};
3939

4040
#[allow(non_camel_case_types)]

0 commit comments

Comments
 (0)