summaryrefslogtreecommitdiffstats
path: root/vendor/socket2/src/socket.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/socket2/src/socket.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/socket2/src/socket.rs')
-rw-r--r--vendor/socket2/src/socket.rs309
1 files changed, 297 insertions, 12 deletions
diff --git a/vendor/socket2/src/socket.rs b/vendor/socket2/src/socket.rs
index bc9b77da0..69d0478dd 100644
--- a/vendor/socket2/src/socket.rs
+++ b/vendor/socket2/src/socket.rs
@@ -1,8 +1,8 @@
// Copyright 2015 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
@@ -11,7 +11,9 @@ use std::io::{self, Read, Write};
#[cfg(not(target_os = "redox"))]
use std::io::{IoSlice, IoSliceMut};
use std::mem::MaybeUninit;
-use std::net::{self, Ipv4Addr, Ipv6Addr, Shutdown};
+#[cfg(not(target_os = "nto"))]
+use std::net::Ipv6Addr;
+use std::net::{self, Ipv4Addr, Shutdown};
#[cfg(unix)]
use std::os::unix::io::{FromRawFd, IntoRawFd};
#[cfg(windows)]
@@ -32,9 +34,11 @@ use crate::{MaybeUninitSlice, RecvFlags};
/// precisely one libc or OS API call which is essentially just a "Rustic
/// translation" of what's below.
///
+/// ## Converting to and from other types
+///
/// This type can be freely converted into the network primitives provided by
/// the standard library, such as [`TcpStream`] or [`UdpSocket`], using the
-/// [`Into`] trait, see the example below.
+/// [`From`] trait, see the example below.
///
/// [`TcpStream`]: std::net::TcpStream
/// [`UdpSocket`]: std::net::UdpSocket
@@ -560,11 +564,36 @@ impl Socket {
/// `peek_from` makes the same safety guarantees regarding the `buf`fer as
/// [`recv`].
///
+ /// # Note: Datagram Sockets
+ /// For datagram sockets, the behavior of this method when `buf` is smaller than
+ /// the datagram at the head of the receive queue differs between Windows and
+ /// Unix-like platforms (Linux, macOS, BSDs, etc: colloquially termed "*nix").
+ ///
+ /// On *nix platforms, the datagram is truncated to the length of `buf`.
+ ///
+ /// On Windows, an error corresponding to `WSAEMSGSIZE` will be returned.
+ ///
+ /// For consistency between platforms, be sure to provide a sufficiently large buffer to avoid
+ /// truncation; the exact size required depends on the underlying protocol.
+ ///
+ /// If you just want to know the sender of the data, try [`peek_sender`].
+ ///
/// [`recv`]: Socket::recv
+ /// [`peek_sender`]: Socket::peek_sender
pub fn peek_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
self.recv_from_with_flags(buf, sys::MSG_PEEK)
}
+ /// Retrieve the sender for the data at the head of the receive queue.
+ ///
+ /// This is equivalent to calling [`peek_from`] with a zero-sized buffer,
+ /// but suppresses the `WSAEMSGSIZE` error on Windows.
+ ///
+ /// [`peek_from`]: Socket::peek_from
+ pub fn peek_sender(&self) -> io::Result<SockAddr> {
+ sys::peek_sender(self.as_raw())
+ }
+
/// Sends data on the socket to a connected peer.
///
/// This is typically used on TCP sockets or datagram sockets which have
@@ -711,6 +740,25 @@ fn set_common_flags(socket: Socket) -> io::Result<Socket> {
Ok(socket)
}
+/// A local interface specified by its index or an address assigned to it.
+///
+/// `Index(0)` and `Address(Ipv4Addr::UNSPECIFIED)` are equivalent and indicate
+/// that an appropriate interface should be selected by the system.
+#[cfg(not(any(
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "solaris",
+)))]
+#[derive(Debug)]
+pub enum InterfaceIndexOrAddress {
+ /// An interface index.
+ Index(u32),
+ /// An address assigned to an interface.
+ Address(Ipv4Addr),
+}
+
/// Socket options get/set using `SOL_SOCKET`.
///
/// Additional documentation can be found in documentation of the OS.
@@ -989,6 +1037,44 @@ fn into_linger(duration: Option<Duration>) -> sys::linger {
/// * Linux: <https://man7.org/linux/man-pages/man7/ip.7.html>
/// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
impl Socket {
+ /// Get the value of the `IP_HDRINCL` option on this socket.
+ ///
+ /// For more information about this option, see [`set_header_included`].
+ ///
+ /// [`set_header_included`]: Socket::set_header_included
+ #[cfg(all(feature = "all", not(target_os = "redox")))]
+ #[cfg_attr(docsrs, doc(all(feature = "all", not(target_os = "redox"))))]
+ pub fn header_included(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_HDRINCL)
+ .map(|included| included != 0)
+ }
+ }
+
+ /// Set the value of the `IP_HDRINCL` option on this socket.
+ ///
+ /// If enabled, the user supplies an IP header in front of the user data.
+ /// Valid only for [`SOCK_RAW`] sockets; see [raw(7)] for more information.
+ /// When this flag is enabled, the values set by `IP_OPTIONS`, [`IP_TTL`],
+ /// and [`IP_TOS`] are ignored.
+ ///
+ /// [`SOCK_RAW`]: Type::RAW
+ /// [raw(7)]: https://man7.org/linux/man-pages/man7/raw.7.html
+ /// [`IP_TTL`]: Socket::set_ttl
+ /// [`IP_TOS`]: Socket::set_tos
+ #[cfg(all(feature = "all", not(target_os = "redox")))]
+ #[cfg_attr(docsrs, doc(all(feature = "all", not(target_os = "redox"))))]
+ pub fn set_header_included(&self, included: bool) -> io::Result<()> {
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_HDRINCL,
+ included as c_int,
+ )
+ }
+ }
+
/// Get the value of the `IP_TRANSPARENT` option on this socket.
///
/// For more information about this option, see [`set_ip_transparent`].
@@ -1014,7 +1100,7 @@ impl Socket {
/// are routed through the TProxy box (i.e., the system
/// hosting the application that employs the IP_TRANSPARENT
/// socket option). Enabling this socket option requires
- /// superuser privileges (the CAP_NET_ADMIN capability).
+ /// superuser privileges (the `CAP_NET_ADMIN` capability).
///
/// TProxy redirection with the iptables TPROXY target also
/// requires that this option be set on the redirected socket.
@@ -1066,6 +1152,139 @@ impl Socket {
}
}
+ /// Join a multicast group using `IP_ADD_MEMBERSHIP` option on this socket.
+ ///
+ /// This function specifies a new multicast group for this socket to join.
+ /// The address must be a valid multicast address, and `interface` specifies
+ /// the local interface with which the system should join the multicast
+ /// group. See [`InterfaceIndexOrAddress`].
+ #[cfg(not(any(
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "nto",
+ )))]
+ pub fn join_multicast_v4_n(
+ &self,
+ multiaddr: &Ipv4Addr,
+ interface: &InterfaceIndexOrAddress,
+ ) -> io::Result<()> {
+ let mreqn = sys::to_mreqn(multiaddr, interface);
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_ADD_MEMBERSHIP,
+ mreqn,
+ )
+ }
+ }
+
+ /// Leave a multicast group using `IP_DROP_MEMBERSHIP` option on this socket.
+ ///
+ /// For more information about this option, see [`join_multicast_v4_n`].
+ ///
+ /// [`join_multicast_v4_n`]: Socket::join_multicast_v4_n
+ #[cfg(not(any(
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "nto",
+ )))]
+ pub fn leave_multicast_v4_n(
+ &self,
+ multiaddr: &Ipv4Addr,
+ interface: &InterfaceIndexOrAddress,
+ ) -> io::Result<()> {
+ let mreqn = sys::to_mreqn(multiaddr, interface);
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_DROP_MEMBERSHIP,
+ mreqn,
+ )
+ }
+ }
+
+ /// Join a multicast SSM channel using `IP_ADD_SOURCE_MEMBERSHIP` option on this socket.
+ ///
+ /// This function specifies a new multicast channel for this socket to join.
+ /// The group must be a valid SSM group address, the source must be the address of the sender
+ /// and `interface` is the address of the local interface with which the system should join the
+ /// multicast group. If it's [`Ipv4Addr::UNSPECIFIED`] (`INADDR_ANY`) then
+ /// an appropriate interface is chosen by the system.
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "fuchsia",
+ target_os = "nto",
+ )))]
+ pub fn join_ssm_v4(
+ &self,
+ source: &Ipv4Addr,
+ group: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreqs = sys::IpMreqSource {
+ imr_multiaddr: sys::to_in_addr(group),
+ imr_interface: sys::to_in_addr(interface),
+ imr_sourceaddr: sys::to_in_addr(source),
+ };
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_ADD_SOURCE_MEMBERSHIP,
+ mreqs,
+ )
+ }
+ }
+
+ /// Leave a multicast group using `IP_DROP_SOURCE_MEMBERSHIP` option on this socket.
+ ///
+ /// For more information about this option, see [`join_ssm_v4`].
+ ///
+ /// [`join_ssm_v4`]: Socket::join_ssm_v4
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "haiku",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "fuchsia",
+ target_os = "nto",
+ )))]
+ pub fn leave_ssm_v4(
+ &self,
+ source: &Ipv4Addr,
+ group: &Ipv4Addr,
+ interface: &Ipv4Addr,
+ ) -> io::Result<()> {
+ let mreqs = sys::IpMreqSource {
+ imr_multiaddr: sys::to_in_addr(group),
+ imr_interface: sys::to_in_addr(interface),
+ imr_sourceaddr: sys::to_in_addr(source),
+ };
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_DROP_SOURCE_MEMBERSHIP,
+ mreqs,
+ )
+ }
+ }
+
/// Get the value of the `IP_MULTICAST_IF` option for this socket.
///
/// For more information about this option, see [`set_multicast_if_v4`].
@@ -1176,7 +1395,7 @@ impl Socket {
/// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
/// documents that not all versions of windows support `IP_TOS`.
#[cfg(not(any(
- target_os = "fuschia",
+ target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
@@ -1191,9 +1410,10 @@ impl Socket {
///
/// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
/// documents that not all versions of windows support `IP_TOS`.
+ ///
/// [`set_tos`]: Socket::set_tos
#[cfg(not(any(
- target_os = "fuschia",
+ target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
@@ -1203,6 +1423,58 @@ impl Socket {
getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_TOS).map(|tos| tos as u32)
}
}
+
+ /// Set the value of the `IP_RECVTOS` option for this socket.
+ ///
+ /// If enabled, the IP_TOS ancillary message is passed with
+ /// incoming packets. It contains a byte which specifies the
+ /// Type of Service/Precedence field of the packet header.
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "windows",
+ target_os = "nto",
+ )))]
+ pub fn set_recv_tos(&self, recv_tos: bool) -> io::Result<()> {
+ let recv_tos = if recv_tos { 1 } else { 0 };
+
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ sys::IPPROTO_IP,
+ sys::IP_RECVTOS,
+ recv_tos as c_int,
+ )
+ }
+ }
+
+ /// Get the value of the `IP_RECVTOS` option for this socket.
+ ///
+ /// For more information about this option, see [`set_recv_tos`].
+ ///
+ /// [`set_recv_tos`]: Socket::set_recv_tos
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "windows",
+ target_os = "nto",
+ )))]
+ pub fn recv_tos(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_RECVTOS)
+ .map(|recv_tos| recv_tos > 0)
+ }
+ }
}
/// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
@@ -1218,6 +1490,7 @@ impl Socket {
/// This function specifies a new multicast group for this socket to join.
/// The address must be a valid multicast address, and `interface` is the
/// index of the interface to join/leave (or 0 to indicate any interface).
+ #[cfg(not(target_os = "nto"))]
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = sys::Ipv6Mreq {
ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
@@ -1241,6 +1514,7 @@ impl Socket {
/// For more information about this option, see [`join_multicast_v6`].
///
/// [`join_multicast_v6`]: Socket::join_multicast_v6
+ #[cfg(not(target_os = "nto"))]
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = sys::Ipv6Mreq {
ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
@@ -1404,11 +1678,22 @@ impl Socket {
impl Socket {
/// Get the value of the `TCP_KEEPIDLE` option on this socket.
///
- /// This returns the value of `SO_KEEPALIVE` on OpenBSD and Haiku,
- /// `TCP_KEEPALIVE` on macOS and iOS, and `TCP_KEEPIDLE` on all other Unix
- /// operating systems.
- #[cfg(any(doc, all(feature = "all", not(windows))))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "all", not(windows)))))]
+ /// This returns the value of `TCP_KEEPALIVE` on macOS and iOS and `TCP_KEEPIDLE` on all other
+ /// supported Unix operating systems.
+ #[cfg(any(
+ doc,
+ all(
+ feature = "all",
+ not(any(windows, target_os = "haiku", target_os = "openbsd"))
+ )
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ not(any(windows, target_os = "haiku", target_os = "openbsd"))
+ )))
+ )]
pub fn keepalive_time(&self) -> io::Result<Duration> {
sys::keepalive_time(self.as_raw())
}