diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/socket2/src/socket.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-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.rs | 309 |
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()) } |