Skip to content

Commit ac13f79

Browse files
authored
Rollup merge of rust-lang#138744 - Mallets:set_ipv6_sock_hop_limit, r=dtolnay
Add methods to TCP and UDP sockets to modify hop limit (refresh of rust-lang#94678) rust-lang#94678 was closed because of time constraints of the original author (`@kckeiks).` This PR is a refresh of rust-lang#94678 where the original proposed changes are ported to the current status of the standard library. In addition, this PR: - implements the change suggested in rust-lang#94678 (comment) - defines `set_multicast_hop_limit_v6` and `multicast_hop_limit_v6 ` only for UDP sockets and not for TCP sockets as originally proposed Issue: rust-lang#139166
2 parents d96c85c + 25fb525 commit ac13f79

File tree

16 files changed

+389
-4
lines changed

16 files changed

+389
-4
lines changed

Diff for: library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@
349349
#![feature(hashmap_internals)]
350350
#![feature(hint_must_use)]
351351
#![feature(ip)]
352+
#![feature(ipv6_hop_limit)]
352353
#![feature(lazy_get)]
353354
#![feature(maybe_uninit_slice)]
354355
#![feature(maybe_uninit_write_slice)]

Diff for: library/std/src/net/tcp.rs

+78
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,46 @@ impl TcpStream {
548548
self.0.ttl()
549549
}
550550

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

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

Diff for: library/std/src/net/tcp/tests.rs

+17
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() {

Diff for: library/std/src/net/udp.rs

+76
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.

Diff for: library/std/src/net/udp/tests.rs

+12
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, _| {

Diff for: library/std/src/sys/net/connection/sgx.rs

+33
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
}

Diff for: library/std/src/sys/net/connection/socket.rs

+36
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,15 @@ impl TcpStream {
454454
Ok(raw as u32)
455455
}
456456

457+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
458+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
459+
}
460+
461+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
462+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
463+
Ok(raw as u8)
464+
}
465+
457466
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
458467
self.inner.take_error()
459468
}
@@ -581,6 +590,15 @@ impl TcpListener {
581590
Ok(raw as u32)
582591
}
583592

593+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
594+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
595+
}
596+
597+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
598+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
599+
Ok(raw as u8)
600+
}
601+
584602
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
585603
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
586604
}
@@ -786,6 +804,24 @@ impl UdpSocket {
786804
Ok(raw as u32)
787805
}
788806

807+
pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
808+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
809+
}
810+
811+
pub fn hop_limit_v6(&self) -> io::Result<u8> {
812+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)?;
813+
Ok(raw as u8)
814+
}
815+
816+
pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
817+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int)
818+
}
819+
820+
pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
821+
let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)?;
822+
Ok(raw as u8)
823+
}
824+
789825
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
790826
self.inner.take_error()
791827
}

Diff for: library/std/src/sys/net/connection/socket/windows.rs

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

3939
#[allow(non_camel_case_types)]

0 commit comments

Comments
 (0)