summaryrefslogtreecommitdiffstats
path: root/vendor/socket2
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/socket2')
-rw-r--r--vendor/socket2/.cargo-checksum.json2
-rw-r--r--vendor/socket2/Cargo.toml49
-rw-r--r--vendor/socket2/README.md4
-rw-r--r--vendor/socket2/src/lib.rs68
-rw-r--r--vendor/socket2/src/sockaddr.rs4
-rw-r--r--vendor/socket2/src/socket.rs309
-rw-r--r--vendor/socket2/src/sys/unix.rs400
-rw-r--r--vendor/socket2/src/sys/windows.rs74
8 files changed, 841 insertions, 69 deletions
diff --git a/vendor/socket2/.cargo-checksum.json b/vendor/socket2/.cargo-checksum.json
index b46b01bcd..0ec9465ba 100644
--- a/vendor/socket2/.cargo-checksum.json
+++ b/vendor/socket2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"132904af796323d037c82381fc97a3f1d696f93c128fc7b2009d827dfdd5230f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b870d442505bc8047b641815c8283f29fc213dcfd1331894802e6ae55cc09f1b","src/lib.rs":"df42802e8487a5491957d13c6fe987a81f0ac4b766809b104279df65908040ea","src/sockaddr.rs":"da658f12e226ea69e2f4880c24c023db1ea11e6609c596fa2abdaf0296fce427","src/socket.rs":"f99ab91141609de7016fa972aad0ba9e4e57bbf0c690cd436b7a0f765bae1a74","src/sockref.rs":"02de263cce039aaddaee5d6c2bb3940bdfae5697a3fc9df47d226fb3cac03cd9","src/sys/unix.rs":"59c6d13c6dd0edbd388df4ac3404765469144ed356ef7a03127a75f11cff6058","src/sys/windows.rs":"9bcd8446e5f0aac866dc1c673568652a40fd54cbf699e33262bd2a1055974437"},"package":"765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"} \ No newline at end of file
+{"files":{"Cargo.toml":"a923f376ccc72eace3803c02342d6ef8c1d0fde8af4fcdb3e86bc55e4b31e800","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b3fadb399050f2755504188e81dec8150f6a1eba86b6410a9ce9c1ea0c850287","src/lib.rs":"0805b736e0cde0ae1d064ff1887f8ae37b219d17309d427be122d5ccd51c116b","src/sockaddr.rs":"a2b7f7c8959b8ff1546d1f1b38f305b22607d7a59c0698e5a8f9cfd81e4b8ede","src/socket.rs":"bd938d210a9763b0ed3395b192698c36c4f88e44adb8f3aaf12a6743efeffa2a","src/sockref.rs":"02de263cce039aaddaee5d6c2bb3940bdfae5697a3fc9df47d226fb3cac03cd9","src/sys/unix.rs":"6db80abf67e6a4555280eba076371798cab333fcb4729fab2a460a5d709f9667","src/sys/windows.rs":"d271c768295c0f84e79f6286aa783ce15ab0265f150195824fdcd10003dada33"},"package":"64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"} \ No newline at end of file
diff --git a/vendor/socket2/Cargo.toml b/vendor/socket2/Cargo.toml
index 521c43c2c..3f1578ccb 100644
--- a/vendor/socket2/Cargo.toml
+++ b/vendor/socket2/Cargo.toml
@@ -12,28 +12,57 @@
[package]
edition = "2018"
name = "socket2"
-version = "0.4.1"
-authors = ["Alex Crichton <alex@alexcrichton.com>", "Thomas de Zeeuw <thomasdezeeuw@gmail.com>"]
-include = ["Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "README.md", "src/**/*.rs"]
-description = "Utilities for handling networking sockets with a maximal amount of configuration\npossible intended.\n"
+version = "0.4.9"
+authors = [
+ "Alex Crichton <alex@alexcrichton.com>",
+ "Thomas de Zeeuw <thomasdezeeuw@gmail.com>",
+]
+include = [
+ "Cargo.toml",
+ "LICENSE-APACHE",
+ "LICENSE-MIT",
+ "README.md",
+ "src/**/*.rs",
+]
+description = """
+Utilities for handling networking sockets with a maximal amount of configuration
+possible intended.
+"""
homepage = "https://github.com/rust-lang/socket2"
documentation = "https://docs.rs/socket2"
readme = "README.md"
-keywords = ["io", "socket", "network"]
-categories = ["api-bindings", "network-programming"]
-license = "MIT/Apache-2.0"
+keywords = [
+ "io",
+ "socket",
+ "network",
+]
+categories = [
+ "api-bindings",
+ "network-programming",
+]
+license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/socket2"
+
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
[package.metadata.playground]
features = ["all"]
[features]
all = []
+
[target."cfg(unix)".dependencies.libc]
-version = "0.2.96"
+version = "0.2.139"
+
[target."cfg(windows)".dependencies.winapi]
version = "0.3.9"
-features = ["handleapi", "ws2ipdef", "ws2tcpip"]
+features = [
+ "handleapi",
+ "ws2ipdef",
+ "ws2tcpip",
+]
diff --git a/vendor/socket2/README.md b/vendor/socket2/README.md
index 45f4cf84b..77963b746 100644
--- a/vendor/socket2/README.md
+++ b/vendor/socket2/README.md
@@ -71,9 +71,9 @@ Socket2 uses 1.46.0 as MSRV.
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
- http://www.apache.org/licenses/LICENSE-2.0)
+ https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
- http://opensource.org/licenses/MIT)
+ https://opensource.org/licenses/MIT)
at your option.
diff --git a/vendor/socket2/src/lib.rs b/vendor/socket2/src/lib.rs
index 6ea3cc229..a2e2ffcb8 100644
--- a/vendor/socket2/src/lib.rs
+++ b/vendor/socket2/src/lib.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.
@@ -34,9 +34,9 @@
//! // Create a TCP listener bound to two addresses.
//! let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?;
//!
+//! socket.set_only_v6(false)?;
//! let address: SocketAddr = "[::1]:12345".parse().unwrap();
//! socket.bind(&address.into())?;
-//! socket.set_only_v6(false)?;
//! socket.listen(128)?;
//!
//! let listener: TcpListener = socket.into();
@@ -50,7 +50,7 @@
//! This crate has a single feature `all`, which enables all functions even ones
//! that are not available on all OSs.
-#![doc(html_root_url = "https://docs.rs/socket2/0.3")]
+#![doc(html_root_url = "https://docs.rs/socket2/0.4")]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
// Show required OS/features on docs.rs.
#![cfg_attr(docsrs, feature(doc_cfg))]
@@ -119,19 +119,28 @@ mod sockaddr;
mod socket;
mod sockref;
-#[cfg(unix)]
-#[path = "sys/unix.rs"]
-mod sys;
-#[cfg(windows)]
-#[path = "sys/windows.rs"]
+#[cfg_attr(unix, path = "sys/unix.rs")]
+#[cfg_attr(windows, path = "sys/windows.rs")]
mod sys;
+#[cfg(not(any(windows, unix)))]
+compile_error!("Socket2 doesn't support the compile target");
+
use sys::c_int;
pub use sockaddr::SockAddr;
pub use socket::Socket;
pub use sockref::SockRef;
+#[cfg(not(any(
+ target_os = "haiku",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "solaris",
+)))]
+pub use socket::InterfaceIndexOrAddress;
+
/// Specification of the communication domain for a socket.
///
/// This is a newtype wrapper around an integer which provides a nicer API in
@@ -282,10 +291,6 @@ impl RecvFlags {
#[repr(transparent)]
pub struct MaybeUninitSlice<'a>(sys::MaybeUninitSlice<'a>);
-unsafe impl<'a> Send for MaybeUninitSlice<'a> {}
-
-unsafe impl<'a> Sync for MaybeUninitSlice<'a> {}
-
impl<'a> fmt::Debug for MaybeUninitSlice<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.0.as_slice(), fmt)
@@ -322,8 +327,22 @@ impl<'a> DerefMut for MaybeUninitSlice<'a> {
/// See [`Socket::set_tcp_keepalive`].
#[derive(Debug, Clone)]
pub struct TcpKeepalive {
+ #[cfg_attr(target_os = "openbsd", allow(dead_code))]
time: Option<Duration>,
+ #[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "nto",
+ )))]
interval: Option<Duration>,
+ #[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "windows",
+ target_os = "nto",
+ )))]
retries: Option<u32>,
}
@@ -332,7 +351,20 @@ impl TcpKeepalive {
pub const fn new() -> TcpKeepalive {
TcpKeepalive {
time: None,
+ #[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "nto",
+ )))]
interval: None,
+ #[cfg(not(any(
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "windows",
+ target_os = "nto",
+ )))]
retries: None,
}
}
@@ -365,9 +397,11 @@ impl TcpKeepalive {
#[cfg(all(
feature = "all",
any(
+ target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
@@ -379,8 +413,11 @@ impl TcpKeepalive {
doc(cfg(all(
feature = "all",
any(
+ target_os = "android",
+ target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
@@ -403,9 +440,11 @@ impl TcpKeepalive {
feature = "all",
any(
doc,
+ target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
@@ -416,8 +455,11 @@ impl TcpKeepalive {
doc(cfg(all(
feature = "all",
any(
+ target_os = "android",
+ target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
diff --git a/vendor/socket2/src/sockaddr.rs b/vendor/socket2/src/sockaddr.rs
index 8a789571f..9ce638e9a 100644
--- a/vendor/socket2/src/sockaddr.rs
+++ b/vendor/socket2/src/sockaddr.rs
@@ -13,6 +13,7 @@ use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH_u;
///
/// `SockAddr`s may be constructed directly to and from the standard library
/// [`SocketAddr`], [`SocketAddrV4`], and [`SocketAddrV6`] types.
+#[derive(Clone)]
pub struct SockAddr {
storage: sockaddr_storage,
len: socklen_t,
@@ -224,7 +225,7 @@ impl From<SocketAddrV4> for SockAddr {
let sockaddr_in = sockaddr_in {
sin_family: AF_INET as sa_family_t,
sin_port: addr.port().to_be(),
- sin_addr: crate::sys::to_in_addr(&addr.ip()),
+ sin_addr: crate::sys::to_in_addr(addr.ip()),
sin_zero: Default::default(),
#[cfg(any(
target_os = "dragonfly",
@@ -301,6 +302,7 @@ impl fmt::Debug for SockAddr {
target_os = "netbsd",
target_os = "openbsd",
target_os = "vxworks",
+ target_os = "nto",
))]
f.field("ss_len", &self.storage.ss_len);
f.field("ss_family", &self.storage.ss_family)
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())
}
diff --git a/vendor/socket2/src/sys/unix.rs b/vendor/socket2/src/sys/unix.rs
index a497830fa..74da8cc20 100644
--- a/vendor/socket2/src/sys/unix.rs
+++ b/vendor/socket2/src/sys/unix.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.
@@ -75,8 +75,24 @@ pub(crate) use libc::{
#[cfg(not(target_os = "redox"))]
pub(crate) use libc::{MSG_TRUNC, SO_OOBINLINE};
// Used in `Socket`.
+#[cfg(not(target_os = "nto"))]
+pub(crate) use libc::ipv6_mreq as Ipv6Mreq;
+#[cfg(all(feature = "all", not(target_os = "redox")))]
+pub(crate) use libc::IP_HDRINCL;
#[cfg(not(any(
- target_os = "fuschia",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "solaris",
+ target_os = "haiku",
+ target_os = "nto",
+)))]
+pub(crate) use libc::IP_RECVTOS;
+#[cfg(not(any(
+ target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
@@ -87,11 +103,23 @@ pub(crate) use libc::SO_LINGER;
#[cfg(target_vendor = "apple")]
pub(crate) use libc::SO_LINGER_SEC as SO_LINGER;
pub(crate) use libc::{
- ip_mreq as IpMreq, ipv6_mreq as Ipv6Mreq, linger, IPPROTO_IP, IPPROTO_IPV6,
- IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY,
- IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL,
- IP_TTL, MSG_OOB, MSG_PEEK, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_RCVBUF,
- SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
+ ip_mreq as IpMreq, linger, IPPROTO_IP, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF,
+ IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
+ IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, MSG_OOB, MSG_PEEK, SOL_SOCKET,
+ SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF,
+ SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
+};
+#[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(crate) use libc::{
+ ip_mreq_source as IpMreqSource, IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP,
};
#[cfg(not(any(
target_os = "dragonfly",
@@ -101,6 +129,7 @@ pub(crate) use libc::{
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
+ target_os = "nto",
target_vendor = "apple"
)))]
pub(crate) use libc::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP};
@@ -135,9 +164,14 @@ pub(crate) use libc::{TCP_KEEPCNT, TCP_KEEPINTVL};
// See this type in the Windows file.
pub(crate) type Bool = c_int;
-#[cfg(target_vendor = "apple")]
+#[cfg(any(target_vendor = "apple", target_os = "nto"))]
use libc::TCP_KEEPALIVE as KEEPALIVE_TIME;
-#[cfg(not(any(target_vendor = "apple", target_os = "haiku", target_os = "openbsd")))]
+#[cfg(not(any(
+ target_vendor = "apple",
+ target_os = "haiku",
+ target_os = "openbsd",
+ target_os = "nto",
+)))]
use libc::TCP_KEEPIDLE as KEEPALIVE_TIME;
/// Helper macro to execute a system call that returns an `io::Result`.
@@ -196,6 +230,7 @@ type IovLen = usize;
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
+ target_os = "nto",
target_vendor = "apple",
))]
type IovLen = c_int;
@@ -414,6 +449,10 @@ pub struct MaybeUninitSlice<'a> {
_lifetime: PhantomData<&'a mut [MaybeUninit<u8>]>,
}
+unsafe impl<'a> Send for MaybeUninitSlice<'a> {}
+
+unsafe impl<'a> Sync for MaybeUninitSlice<'a> {}
+
impl<'a> MaybeUninitSlice<'a> {
pub(crate) fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
MaybeUninitSlice {
@@ -713,6 +752,15 @@ pub(crate) fn recv_from(
}
}
+pub(crate) fn peek_sender(fd: Socket) -> io::Result<SockAddr> {
+ // Unix-like platforms simply truncate the returned data, so this implementation is trivial.
+ // However, for Windows this requires suppressing the `WSAEMSGSIZE` error,
+ // so that requires a different approach.
+ // NOTE: macOS does not populate `sockaddr` if you pass a zero-sized buffer.
+ let (_, sender) = recv_from(fd, &mut [MaybeUninit::uninit(); 8], MSG_PEEK)?;
+ Ok(sender)
+}
+
#[cfg(not(target_os = "redox"))]
pub(crate) fn recv_vectored(
fd: Socket,
@@ -866,6 +914,7 @@ fn into_timeval(duration: Option<Duration>) -> libc::timeval {
}
#[cfg(feature = "all")]
+#[cfg(not(any(target_os = "haiku", target_os = "openbsd")))]
pub(crate) fn keepalive_time(fd: Socket) -> io::Result<Duration> {
unsafe {
getsockopt::<c_int>(fd, IPPROTO_TCP, KEEPALIVE_TIME)
@@ -875,7 +924,7 @@ pub(crate) fn keepalive_time(fd: Socket) -> io::Result<Duration> {
#[allow(unused_variables)]
pub(crate) fn set_tcp_keepalive(fd: Socket, keepalive: &TcpKeepalive) -> io::Result<()> {
- #[cfg(not(any(target_os = "haiku", target_os = "openbsd")))]
+ #[cfg(not(any(target_os = "haiku", target_os = "openbsd", target_os = "nto")))]
if let Some(time) = keepalive.time {
let secs = into_secs(time);
unsafe { setsockopt(fd, libc::IPPROTO_TCP, KEEPALIVE_TIME, secs)? }
@@ -902,10 +951,16 @@ pub(crate) fn set_tcp_keepalive(fd: Socket, keepalive: &TcpKeepalive) -> io::Res
}
}
+ #[cfg(target_os = "nto")]
+ if let Some(time) = keepalive.time {
+ let secs = into_timeval(Some(time));
+ unsafe { setsockopt(fd, libc::IPPROTO_TCP, KEEPALIVE_TIME, secs)? }
+ }
+
Ok(())
}
-#[cfg(not(any(target_os = "haiku", target_os = "openbsd")))]
+#[cfg(not(any(target_os = "haiku", target_os = "openbsd", target_os = "nto")))]
fn into_secs(duration: Duration) -> c_int {
min(duration.as_secs(), c_int::max_value() as u64) as c_int
}
@@ -993,6 +1048,33 @@ pub(crate) fn from_in6_addr(addr: in6_addr) -> Ipv6Addr {
Ipv6Addr::from(addr.s6_addr)
}
+#[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(crate) fn to_mreqn(
+ multiaddr: &Ipv4Addr,
+ interface: &crate::socket::InterfaceIndexOrAddress,
+) -> libc::ip_mreqn {
+ match interface {
+ crate::socket::InterfaceIndexOrAddress::Index(interface) => libc::ip_mreqn {
+ imr_multiaddr: to_in_addr(multiaddr),
+ imr_address: to_in_addr(&Ipv4Addr::UNSPECIFIED),
+ imr_ifindex: *interface as _,
+ },
+ crate::socket::InterfaceIndexOrAddress::Address(interface) => libc::ip_mreqn {
+ imr_multiaddr: to_in_addr(multiaddr),
+ imr_address: to_in_addr(interface),
+ imr_ifindex: 0,
+ },
+ }
+}
+
/// Unix only API.
impl crate::Socket {
/// Accept a new incoming connection from this listener.
@@ -1276,6 +1358,162 @@ impl crate::Socket {
}
}
+ /// Get the value of the `TCP_CORK` option on this socket.
+ ///
+ /// For more information about this option, see [`set_cork`].
+ ///
+ /// [`set_cork`]: Socket::set_cork
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn cork(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<Bool>(self.as_raw(), libc::IPPROTO_TCP, libc::TCP_CORK)
+ .map(|cork| cork != 0)
+ }
+ }
+
+ /// Set the value of the `TCP_CORK` option on this socket.
+ ///
+ /// If set, don't send out partial frames. All queued partial frames are
+ /// sent when the option is cleared again. There is a 200 millisecond ceiling on
+ /// the time for which output is corked by `TCP_CORK`. If this ceiling is reached,
+ /// then queued data is automatically transmitted.
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn set_cork(&self, cork: bool) -> io::Result<()> {
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ libc::IPPROTO_TCP,
+ libc::TCP_CORK,
+ cork as c_int,
+ )
+ }
+ }
+
+ /// Get the value of the `TCP_QUICKACK` option on this socket.
+ ///
+ /// For more information about this option, see [`set_quickack`].
+ ///
+ /// [`set_quickack`]: Socket::set_quickack
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn quickack(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<Bool>(self.as_raw(), libc::IPPROTO_TCP, libc::TCP_QUICKACK)
+ .map(|quickack| quickack != 0)
+ }
+ }
+
+ /// Set the value of the `TCP_QUICKACK` option on this socket.
+ ///
+ /// If set, acks are sent immediately, rather than delayed if needed in accordance to normal
+ /// TCP operation. This flag is not permanent, it only enables a switch to or from quickack mode.
+ /// Subsequent operation of the TCP protocol will once again enter/leave quickack mode depending on
+ /// internal protocol processing and factors such as delayed ack timeouts occurring and data transfer.
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn set_quickack(&self, quickack: bool) -> io::Result<()> {
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ libc::IPPROTO_TCP,
+ libc::TCP_QUICKACK,
+ quickack as c_int,
+ )
+ }
+ }
+
+ /// Get the value of the `TCP_THIN_LINEAR_TIMEOUTS` option on this socket.
+ ///
+ /// For more information about this option, see [`set_thin_linear_timeouts`].
+ ///
+ /// [`set_thin_linear_timeouts`]: Socket::set_thin_linear_timeouts
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn thin_linear_timeouts(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<Bool>(
+ self.as_raw(),
+ libc::IPPROTO_TCP,
+ libc::TCP_THIN_LINEAR_TIMEOUTS,
+ )
+ .map(|timeouts| timeouts != 0)
+ }
+ }
+
+ /// Set the value of the `TCP_THIN_LINEAR_TIMEOUTS` option on this socket.
+ ///
+ /// If set, the kernel will dynamically detect a thin-stream connection if there are less than four packets in flight.
+ /// With less than four packets in flight the normal TCP fast retransmission will not be effective.
+ /// The kernel will modify the retransmission to avoid the very high latencies that thin stream suffer because of exponential backoff.
+ #[cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ ))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(
+ feature = "all",
+ any(target_os = "android", target_os = "fuchsia", target_os = "linux")
+ )))
+ )]
+ pub fn set_thin_linear_timeouts(&self, timeouts: bool) -> io::Result<()> {
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ libc::IPPROTO_TCP,
+ libc::TCP_THIN_LINEAR_TIMEOUTS,
+ timeouts as c_int,
+ )
+ }
+ }
+
/// Gets the value for the `SO_BINDTODEVICE` option on this socket.
///
/// This value gets the socket binded device's interface name.
@@ -1295,15 +1533,13 @@ impl crate::Socket {
let mut buf: [MaybeUninit<u8>; libc::IFNAMSIZ] =
unsafe { MaybeUninit::uninit().assume_init() };
let mut len = buf.len() as libc::socklen_t;
- unsafe {
- syscall!(getsockopt(
- self.as_raw(),
- libc::SOL_SOCKET,
- libc::SO_BINDTODEVICE,
- buf.as_mut_ptr().cast(),
- &mut len,
- ))?;
- }
+ syscall!(getsockopt(
+ self.as_raw(),
+ libc::SOL_SOCKET,
+ libc::SO_BINDTODEVICE,
+ buf.as_mut_ptr().cast(),
+ &mut len,
+ ))?;
if len == 0 {
Ok(None)
} else {
@@ -1347,6 +1583,22 @@ impl crate::Socket {
.map(|_| ())
}
+ /// Sets the value for the `SO_SETFIB` option on this socket.
+ ///
+ /// Bind socket to the specified forwarding table (VRF) on a FreeBSD.
+ #[cfg(all(feature = "all", any(target_os = "freebsd")))]
+ #[cfg_attr(docsrs, doc(cfg(all(feature = "all", any(target_os = "freebsd")))))]
+ pub fn set_fib(&self, fib: u32) -> io::Result<()> {
+ syscall!(setsockopt(
+ self.as_raw(),
+ libc::SOL_SOCKET,
+ libc::SO_SETFIB,
+ (&fib as *const u32).cast(),
+ mem::size_of::<u32>() as libc::socklen_t,
+ ))
+ .map(|_| ())
+ }
+
/// Sets the value for `IP_BOUND_IF` option on this socket.
///
/// If a socket is bound to an interface, only packets received from that
@@ -1477,8 +1729,8 @@ impl crate::Socket {
)]
pub fn freebind(&self) -> io::Result<bool> {
unsafe {
- getsockopt::<c_int>(self.as_raw(), libc::SOL_SOCKET, libc::IP_FREEBIND)
- .map(|reuse| reuse != 0)
+ getsockopt::<c_int>(self.as_raw(), libc::SOL_IP, libc::IP_FREEBIND)
+ .map(|freebind| freebind != 0)
}
}
@@ -1500,13 +1752,78 @@ impl crate::Socket {
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
)))
)]
- pub fn set_freebind(&self, reuse: bool) -> io::Result<()> {
+ pub fn set_freebind(&self, freebind: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.as_raw(),
- libc::SOL_SOCKET,
+ libc::SOL_IP,
libc::IP_FREEBIND,
- reuse as c_int,
+ freebind as c_int,
+ )
+ }
+ }
+
+ /// Get the value of the `IPV6_FREEBIND` option on this socket.
+ ///
+ /// This is an IPv6 counterpart of `IP_FREEBIND` socket option on
+ /// Android/Linux. For more information about this option, see
+ /// [`set_freebind`].
+ ///
+ /// [`set_freebind`]: crate::Socket::set_freebind
+ #[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
+ )]
+ pub fn freebind_ipv6(&self) -> io::Result<bool> {
+ unsafe {
+ getsockopt::<c_int>(self.as_raw(), libc::SOL_IPV6, libc::IPV6_FREEBIND)
+ .map(|freebind| freebind != 0)
+ }
+ }
+
+ /// Set value for the `IPV6_FREEBIND` option on this socket.
+ ///
+ /// This is an IPv6 counterpart of `IP_FREEBIND` socket option on
+ /// Android/Linux. For more information about this option, see
+ /// [`set_freebind`].
+ ///
+ /// [`set_freebind`]: crate::Socket::set_freebind
+ ///
+ /// # Examples
+ ///
+ /// On Linux:
+ ///
+ /// ```
+ /// use socket2::{Domain, Socket, Type};
+ /// use std::io::{self, Error, ErrorKind};
+ ///
+ /// fn enable_freebind(socket: &Socket) -> io::Result<()> {
+ /// match socket.domain()? {
+ /// Domain::IPV4 => socket.set_freebind(true)?,
+ /// Domain::IPV6 => socket.set_freebind_ipv6(true)?,
+ /// _ => return Err(Error::new(ErrorKind::Other, "unsupported domain")),
+ /// };
+ /// Ok(())
+ /// }
+ ///
+ /// # fn main() -> io::Result<()> {
+ /// # let socket = Socket::new(Domain::IPV6, Type::STREAM, None)?;
+ /// # enable_freebind(&socket)
+ /// # }
+ /// ```
+ #[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
+ #[cfg_attr(
+ docsrs,
+ doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
+ )]
+ pub fn set_freebind_ipv6(&self, freebind: bool) -> io::Result<()> {
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ libc::SOL_IPV6,
+ libc::IPV6_FREEBIND,
+ freebind as c_int,
)
}
}
@@ -1691,6 +2008,37 @@ impl crate::Socket {
})
}
}
+
+ /// Attach Berkeley Packet Filter(BPF) on this socket.
+ ///
+ /// BPF allows a user-space program to attach a filter onto any socket
+ /// and allow or disallow certain types of data to come through the socket.
+ ///
+ /// For more information about this option, see [filter](https://www.kernel.org/doc/html/v5.12/networking/filter.html)
+ #[cfg(all(feature = "all", any(target_os = "linux", target_os = "android")))]
+ pub fn attach_filter(&self, filters: &[libc::sock_filter]) -> io::Result<()> {
+ let prog = libc::sock_fprog {
+ len: filters.len() as u16,
+ filter: filters.as_ptr() as *mut _,
+ };
+
+ unsafe {
+ setsockopt(
+ self.as_raw(),
+ libc::SOL_SOCKET,
+ libc::SO_ATTACH_FILTER,
+ prog,
+ )
+ }
+ }
+
+ /// Detach Berkeley Packet Filter(BPF) from this socket.
+ ///
+ /// For more information about this option, see [`attach_filter`]
+ #[cfg(all(feature = "all", any(target_os = "linux", target_os = "android")))]
+ pub fn detach_filter(&self) -> io::Result<()> {
+ unsafe { setsockopt(self.as_raw(), libc::SOL_SOCKET, libc::SO_DETACH_FILTER, 0) }
+ }
}
#[cfg_attr(docsrs, doc(cfg(unix)))]
diff --git a/vendor/socket2/src/sys/windows.rs b/vendor/socket2/src/sys/windows.rs
index cd28f97d9..0e36a1ccf 100644
--- a/vendor/socket2/src/sys/windows.rs
+++ b/vendor/socket2/src/sys/windows.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.
@@ -32,6 +32,7 @@ use winapi::um::winsock2::{
self as sock, u_long, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND,
WSAPOLLFD,
};
+use winapi::um::winsock2::{SOCKET_ERROR, WSAEMSGSIZE, WSAESHUTDOWN};
use crate::{RecvFlags, SockAddr, TcpKeepalive, Type};
@@ -66,11 +67,14 @@ pub(crate) use winapi::shared::ws2def::{
IPPROTO_IP, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE,
SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
};
+#[cfg(feature = "all")]
+pub(crate) use winapi::shared::ws2ipdef::IP_HDRINCL;
pub(crate) use winapi::shared::ws2ipdef::{
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MREQ as Ipv6Mreq, IPV6_MULTICAST_HOPS,
IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP,
- IP_DROP_MEMBERSHIP, IP_MREQ as IpMreq, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL,
- IP_TOS, IP_TTL,
+ IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP, IP_MREQ as IpMreq,
+ IP_MREQ_SOURCE as IpMreqSource, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TOS,
+ IP_TTL,
};
pub(crate) use winapi::um::winsock2::{linger, MSG_OOB, MSG_PEEK};
pub(crate) const IPPROTO_IPV6: c_int = winapi::shared::ws2def::IPPROTO_IPV6 as c_int;
@@ -157,6 +161,10 @@ pub struct MaybeUninitSlice<'a> {
_lifetime: PhantomData<&'a mut [MaybeUninit<u8>]>,
}
+unsafe impl<'a> Send for MaybeUninitSlice<'a> {}
+
+unsafe impl<'a> Sync for MaybeUninitSlice<'a> {}
+
impl<'a> MaybeUninitSlice<'a> {
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> MaybeUninitSlice<'a> {
assert!(buf.len() <= ULONG::MAX as usize);
@@ -459,6 +467,38 @@ pub(crate) fn recv_from(
}
}
+pub(crate) fn peek_sender(socket: Socket) -> io::Result<SockAddr> {
+ // Safety: `recvfrom` initialises the `SockAddr` for us.
+ let ((), sender) = unsafe {
+ SockAddr::init(|storage, addrlen| {
+ let res = syscall!(
+ recvfrom(
+ socket,
+ // Windows *appears* not to care if you pass a null pointer.
+ ptr::null_mut(),
+ 0,
+ MSG_PEEK,
+ storage.cast(),
+ addrlen,
+ ),
+ PartialEq::eq,
+ SOCKET_ERROR
+ );
+ match res {
+ Ok(_n) => Ok(()),
+ Err(e) => match e.raw_os_error() {
+ Some(code) if code == (WSAESHUTDOWN as i32) || code == (WSAEMSGSIZE as i32) => {
+ Ok(())
+ }
+ _ => Err(e),
+ },
+ }
+ })
+ }?;
+
+ Ok(sender)
+}
+
pub(crate) fn recv_from_vectored(
socket: Socket,
bufs: &mut [crate::MaybeUninitSlice<'_>],
@@ -735,6 +775,32 @@ pub(crate) fn from_in6_addr(addr: in6_addr) -> Ipv6Addr {
Ipv6Addr::from(*unsafe { addr.u.Byte() })
}
+pub(crate) fn to_mreqn(
+ multiaddr: &Ipv4Addr,
+ interface: &crate::socket::InterfaceIndexOrAddress,
+) -> IpMreq {
+ IpMreq {
+ imr_multiaddr: to_in_addr(multiaddr),
+ // Per https://docs.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-ip_mreq#members:
+ //
+ // imr_interface
+ //
+ // The local IPv4 address of the interface or the interface index on
+ // which the multicast group should be joined or dropped. This value is
+ // in network byte order. If this member specifies an IPv4 address of
+ // 0.0.0.0, the default IPv4 multicast interface is used.
+ //
+ // To use an interface index of 1 would be the same as an IP address of
+ // 0.0.0.1.
+ imr_interface: match interface {
+ crate::socket::InterfaceIndexOrAddress::Index(interface) => {
+ to_in_addr(&(*interface).into())
+ }
+ crate::socket::InterfaceIndexOrAddress::Address(interface) => to_in_addr(interface),
+ },
+ }
+}
+
/// Windows only API.
impl crate::Socket {
/// Sets `HANDLE_FLAG_INHERIT` using `SetHandleInformation`.