summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/src/sys/socket/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/nix/src/sys/socket/mod.rs')
-rw-r--r--third_party/rust/nix/src/sys/socket/mod.rs943
1 files changed, 388 insertions, 555 deletions
diff --git a/third_party/rust/nix/src/sys/socket/mod.rs b/third_party/rust/nix/src/sys/socket/mod.rs
index 78dd617c55..3d1651bd3f 100644
--- a/third_party/rust/nix/src/sys/socket/mod.rs
+++ b/third_party/rust/nix/src/sys/socket/mod.rs
@@ -1,7 +1,7 @@
//! Socket interface functions
//!
//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(any(target_os = "freebsd", linux_android))]
#[cfg(feature = "uio")]
use crate::sys::time::TimeSpec;
#[cfg(not(target_os = "redox"))]
@@ -9,16 +9,16 @@ use crate::sys::time::TimeSpec;
use crate::sys::time::TimeVal;
use crate::{errno::Errno, Result};
use cfg_if::cfg_if;
-use libc::{self, c_int, c_void, size_t, socklen_t};
+use libc::{self, c_int, size_t, socklen_t};
#[cfg(all(feature = "uio", not(target_os = "redox")))]
use libc::{
- iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
+ c_void, iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
};
#[cfg(not(target_os = "redox"))]
use std::io::{IoSlice, IoSliceMut};
#[cfg(feature = "net")]
use std::net;
-use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, RawFd, OwnedFd};
+use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
use std::{mem, ptr};
#[deny(missing_docs)]
@@ -34,35 +34,25 @@ pub mod sockopt;
pub use self::addr::{SockaddrLike, SockaddrStorage};
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+#[cfg(solarish)]
pub use self::addr::{AddressFamily, UnixAddr};
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+#[cfg(not(solarish))]
pub use self::addr::{AddressFamily, UnixAddr};
-#[cfg(not(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku",
- target_os = "redox",
-)))]
+#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))]
#[cfg(feature = "net")]
pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6};
-#[cfg(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku",
- target_os = "redox",
-))]
+#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))]
#[cfg(feature = "net")]
pub use self::addr::{SockaddrIn, SockaddrIn6};
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
pub use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[cfg(feature = "ioctl")]
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+#[cfg(any(linux_android, apple_targets))]
pub use crate::sys::socket::addr::vsock::VsockAddr;
#[cfg(all(feature = "uio", not(target_os = "redox")))]
@@ -132,121 +122,108 @@ pub enum SockProtocol {
Udp = libc::IPPROTO_UDP,
/// Raw sockets ([raw(7)](https://man7.org/linux/man-pages/man7/raw.7.html))
Raw = libc::IPPROTO_RAW,
- /// Allows applications and other KEXTs to be notified when certain kernel events occur
- /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- KextEvent = libc::SYSPROTO_EVENT,
/// Allows applications to configure and control a KEXT
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(apple_targets)]
KextControl = libc::SYSPROTO_CONTROL,
/// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
// parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkRoute = libc::NETLINK_ROUTE,
/// Reserved for user-mode socket protocols
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkUserSock = libc::NETLINK_USERSOCK,
/// Query information about sockets of various protocol families from the kernel
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
/// Netfilter/iptables ULOG.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkNFLOG = libc::NETLINK_NFLOG,
/// SELinux event notifications.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSELinux = libc::NETLINK_SELINUX,
/// Open-iSCSI
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkISCSI = libc::NETLINK_ISCSI,
/// Auditing
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkAudit = libc::NETLINK_AUDIT,
/// Access to FIB lookup from user space
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
/// Netfilter subsystem
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkNetFilter = libc::NETLINK_NETFILTER,
/// SCSI Transports
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
/// Infiniband RDMA
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkRDMA = libc::NETLINK_RDMA,
/// Transport IPv6 packets from netfilter to user space. Used by ip6_queue kernel module.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
/// DECnet routing messages
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
/// Kernel messages to user space
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
/// Generic netlink family for simplified netlink usage.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkGeneric = libc::NETLINK_GENERIC,
/// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
/// configuration of the kernel crypto API.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
NetlinkCrypto = libc::NETLINK_CRYPTO,
/// Non-DIX type protocol number defined for the Ethernet IEEE 802.3 interface that allows packets of all protocols
/// defined in the interface to be received.
/// ([ref](https://man7.org/linux/man-pages/man7/packet.7.html))
// The protocol number is fed into the socket syscall in network byte order.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
EthAll = (libc::ETH_P_ALL as u16).to_be() as i32,
+ /// ICMP protocol ([icmp(7)](https://man7.org/linux/man-pages/man7/icmp.7.html))
+ Icmp = libc::IPPROTO_ICMP,
+ /// ICMPv6 protocol (ICMP over IPv6)
+ IcmpV6 = libc::IPPROTO_ICMPV6,
+}
+
+impl SockProtocol {
/// The Controller Area Network raw socket protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CanRaw = libc::CAN_RAW,
-}
+ #[allow(non_upper_case_globals)]
+ pub const CanRaw: SockProtocol = SockProtocol::Icmp; // Matches libc::CAN_RAW
-impl SockProtocol {
/// The Controller Area Network broadcast manager protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(non_upper_case_globals)]
pub const CanBcm: SockProtocol = SockProtocol::NetlinkUserSock; // Matches libc::CAN_BCM
+
+ /// Allows applications and other KEXTs to be notified when certain kernel events occur
+ /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
+ #[cfg(apple_targets)]
+ #[allow(non_upper_case_globals)]
+ pub const KextEvent: SockProtocol = SockProtocol::Icmp; // Matches libc::SYSPROTO_EVENT
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
libc_bitflags! {
/// Configuration flags for `SO_TIMESTAMPING` interface
///
@@ -276,33 +253,23 @@ libc_bitflags! {
/// Additional socket options
pub struct SockFlag: c_int {
/// Set non-blocking mode on the new socket
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android,
+ freebsdlike,
+ netbsdlike,
+ solarish))]
SOCK_NONBLOCK;
/// Set close-on-exec on the new descriptor
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android,
+ freebsdlike,
+ netbsdlike,
+ solarish))]
SOCK_CLOEXEC;
/// Return `EPIPE` instead of raising `SIGPIPE`
#[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SOCK_NOSIGPIPE;
/// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
/// to the DNS port (typically 53)
#[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
SOCK_DNS;
}
}
@@ -333,7 +300,6 @@ libc_bitflags! {
/// the calling process and as well as other processes that hold
/// file descriptors referring to the same open file description.
#[cfg(not(target_os = "aix"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
MSG_DONTWAIT;
/// Receive flags: Control Data was discarded (buffer too small)
MSG_CTRUNC;
@@ -352,8 +318,7 @@ libc_bitflags! {
/// This flag specifies that queued errors should be received from
/// the socket error queue. (For more details, see
/// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
MSG_ERRQUEUE;
/// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
/// file descriptor using the `SCM_RIGHTS` operation (described in
@@ -362,44 +327,48 @@ libc_bitflags! {
/// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
///
/// Only used in [`recvmsg`](fn.recvmsg.html) function.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, freebsdlike, netbsdlike))]
MSG_CMSG_CLOEXEC;
/// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
/// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
+ #[cfg(any(linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
target_os = "fuchsia",
- target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "haiku"))]
MSG_NOSIGNAL;
/// Turns on [`MSG_DONTWAIT`] after the first message has been received (only for
/// `recvmmsg()`).
- #[cfg(any(target_os = "android",
+ #[cfg(any(linux_android,
+ netbsdlike,
target_os = "fuchsia",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ target_os = "freebsd"))]
MSG_WAITFORONE;
}
}
+#[cfg(target_os = "freebsd")]
+libc_enum! {
+ /// A selector for which clock to use when generating packet timestamps.
+ /// Used when setting [`TsClock`](crate::sys::socket::sockopt::TsClock) on a socket.
+ /// (For more details, see [setsockopt(2)](https://man.freebsd.org/cgi/man.cgi?setsockopt)).
+ #[repr(i32)]
+ #[non_exhaustive]
+ pub enum SocketTimestamp {
+ /// Microsecond resolution, realtime. This is the default.
+ SO_TS_REALTIME_MICRO,
+ /// Sub-nanosecond resolution, realtime.
+ SO_TS_BINTIME,
+ /// Nanosecond resolution, realtime.
+ SO_TS_REALTIME,
+ /// Nanosecond resolution, monotonic.
+ SO_TS_MONOTONIC,
+ }
+}
+
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SO_PEERCRED` ancillary message
@@ -454,7 +423,7 @@ cfg_if! {
uc.0
}
}
- } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
+ } else if #[cfg(freebsdlike)] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
@@ -487,7 +456,7 @@ cfg_if! {
pub fn groups(&self) -> &[libc::gid_t] {
unsafe {
std::slice::from_raw_parts(
- self.0.cmcred_groups.as_ptr() as *const libc::gid_t,
+ self.0.cmcred_groups.as_ptr(),
self.0.cmcred_ngroups as _
)
}
@@ -503,12 +472,7 @@ cfg_if! {
}
cfg_if! {
- if #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
- ))] {
+ if #[cfg(any(freebsdlike, apple_targets))] {
/// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred)
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -603,8 +567,6 @@ feature! {
/// let _ = cmsg_space!(RawFd, TimeVal);
/// # }
/// ```
-// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
-// stack-allocated array.
#[macro_export]
macro_rules! cmsg_space {
( $( $x:ty ),* ) => {
@@ -617,7 +579,7 @@ macro_rules! cmsg_space {
#[inline]
#[doc(hidden)]
-pub fn cmsg_space<T>() -> usize {
+pub const fn cmsg_space<T>() -> usize {
// SAFETY: CMSG_SPACE is always safe
unsafe { libc::CMSG_SPACE(mem::size_of::<T>() as libc::c_uint) as usize }
}
@@ -677,7 +639,7 @@ impl<'a> Iterator for CmsgIterator<'a> {
}
/// A type-safe wrapper around a single control message, as used with
-/// [`recvmsg`](#fn.recvmsg).
+/// [`recvmsg`].
///
/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
// Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
@@ -692,12 +654,10 @@ pub enum ControlMessageOwned {
/// Received version of [`ControlMessage::ScmRights`]
ScmRights(Vec<RawFd>),
/// Received version of [`ControlMessage::ScmCredentials`]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmCredentials(UnixCredentials),
/// Received version of [`ControlMessage::ScmCreds`]
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
ScmCreds(UnixCredentials),
/// A message of type `SCM_TIMESTAMP`, containing the time the
/// packet was received by the kernel.
@@ -760,62 +720,44 @@ pub enum ControlMessageOwned {
/// A set of nanosecond resolution timestamps
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ScmTimestampsns(Timestamps),
/// Nanoseconds resolution timestamp
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmTimestampns(TimeSpec),
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
+ /// Realtime clock timestamp
+ ///
+ /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
+ #[cfg(target_os = "freebsd")]
+ ScmRealtime(TimeSpec),
+ /// Monotonic clock timestamp
+ ///
+ /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
+ #[cfg(target_os = "freebsd")]
+ ScmMonotonic(TimeSpec),
+ #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4PacketInfo(libc::in_pktinfo),
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, bsd))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6PacketInfo(libc::in6_pktinfo),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvIf(libc::sockaddr_dl),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvDstAddr(libc::in_addr),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4OrigDstAddr(libc::sockaddr_in),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6OrigDstAddr(libc::sockaddr_in6),
@@ -841,28 +783,31 @@ pub enum ControlMessageOwned {
///
/// `RxqOvfl` socket option should be enabled on a socket
/// to allow receiving the drop counter.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
RxqOvfl(u32),
/// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
/// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
+ /// `SOL_TLS` messages of type `TLS_GET_RECORD_TYPE`
+ #[cfg(any(target_os = "linux"))]
+ TlsGetRecordType(TlsGetRecordType),
+
/// Catch-all variant for unimplemented cmsg types.
#[doc(hidden)]
Unknown(UnknownCmsg),
}
/// For representing packet timestamps via `SO_TIMESTAMPING` interface
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Timestamps {
/// software based timestamp, usually one containing data
@@ -873,6 +818,33 @@ pub struct Timestamps {
pub hw_raw: TimeSpec,
}
+/// These constants correspond to TLS 1.2 message types, as defined in
+/// RFC 5246, Appendix A.1
+#[cfg(any(target_os = "linux"))]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[repr(u8)]
+#[non_exhaustive]
+pub enum TlsGetRecordType {
+ ChangeCipherSpec ,
+ Alert,
+ Handshake,
+ ApplicationData,
+ Unknown(u8),
+}
+
+#[cfg(any(target_os = "linux"))]
+impl From<u8> for TlsGetRecordType {
+ fn from(x: u8) -> Self {
+ match x {
+ 20 => TlsGetRecordType::ChangeCipherSpec,
+ 21 => TlsGetRecordType::Alert,
+ 22 => TlsGetRecordType::Handshake,
+ 23 => TlsGetRecordType::ApplicationData,
+ _ => TlsGetRecordType::Unknown(x),
+ }
+ }
+}
+
impl ControlMessageOwned {
/// Decodes a `ControlMessageOwned` from raw bytes.
///
@@ -885,7 +857,7 @@ impl ControlMessageOwned {
#[allow(clippy::cast_ptr_alignment)]
unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
{
- let p = CMSG_DATA(header);
+ let p = unsafe { CMSG_DATA(header) };
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
let len = header as *const _ as usize + header.cmsg_len as usize
@@ -895,158 +867,151 @@ impl ControlMessageOwned {
let n = len / mem::size_of::<RawFd>();
let mut fds = Vec::with_capacity(n);
for i in 0..n {
- let fdp = (p as *const RawFd).add(i);
- fds.push(ptr::read_unaligned(fdp));
+ unsafe {
+ let fdp = (p as *const RawFd).add(i);
+ fds.push(ptr::read_unaligned(fdp));
+ }
}
ControlMessageOwned::ScmRights(fds)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
- let cred: libc::ucred = ptr::read_unaligned(p as *const _);
+ let cred: libc::ucred = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmCredentials(cred.into())
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
(libc::SOL_SOCKET, libc::SCM_CREDS) => {
- let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
+ let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmCreds(cred.into())
}
#[cfg(not(any(target_os = "aix", target_os = "haiku")))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
- let tv: libc::timeval = ptr::read_unaligned(p as *const _);
+ let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
- let ts: libc::timespec = ptr::read_unaligned(p as *const _);
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(target_os = "freebsd")]
+ (libc::SOL_SOCKET, libc::SCM_REALTIME) => {
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
+ ControlMessageOwned::ScmRealtime(TimeSpec::from(ts))
+ }
+ #[cfg(target_os = "freebsd")]
+ (libc::SOL_SOCKET, libc::SCM_MONOTONIC) => {
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
+ ControlMessageOwned::ScmMonotonic(TimeSpec::from(ts))
+ }
+ #[cfg(linux_android)]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
let tp = p as *const libc::timespec;
- let ts: libc::timespec = ptr::read_unaligned(tp);
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp) };
let system = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(1));
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(1)) };
let hw_trans = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(2));
+ let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(2)) };
let hw_raw = TimeSpec::from(ts);
let timestamping = Timestamps { system, hw_trans, hw_raw };
ControlMessageOwned::ScmTimestampsns(timestamping)
}
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
- ))]
+ #[cfg(any(target_os = "freebsd", linux_android, apple_targets))]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
+ let info = unsafe { ptr::read_unaligned(p as *const libc::in6_pktinfo) };
ControlMessageOwned::Ipv6PacketInfo(info)
}
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
+ let info = unsafe { ptr::read_unaligned(p as *const libc::in_pktinfo) };
ControlMessageOwned::Ipv4PacketInfo(info)
}
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVIF) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_dl) };
ControlMessageOwned::Ipv4RecvIf(dl)
},
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
+ #[cfg(bsd)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::in_addr);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::in_addr) };
ControlMessageOwned::Ipv4RecvDstAddr(dl)
},
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in) };
ControlMessageOwned::Ipv4OrigDstAddr(dl)
},
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
(libc::SOL_UDP, libc::UDP_GRO) => {
- let gso_size: u16 = ptr::read_unaligned(p as *const _);
+ let gso_size: u16 = unsafe { ptr::read_unaligned(p as *const _) };
ControlMessageOwned::UdpGroSegments(gso_size)
},
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
(libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
- let drop_counter = ptr::read_unaligned(p as *const u32);
+ let drop_counter = unsafe { ptr::read_unaligned(p as *const u32) };
ControlMessageOwned::RxqOvfl(drop_counter)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
(libc::IPPROTO_IP, libc::IP_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in>(p, len);
+ let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in>(p, len) };
ControlMessageOwned::Ipv4RecvErr(err, addr)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in6>(p, len);
+ let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in6>(p, len) };
ControlMessageOwned::Ipv6RecvErr(err, addr)
},
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+ #[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg(feature = "net")]
(libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in6);
+ let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in6) };
ControlMessageOwned::Ipv6OrigDstAddr(dl)
},
+ #[cfg(any(target_os = "linux"))]
+ (libc::SOL_TLS, libc::TLS_GET_RECORD_TYPE) => {
+ let content_type = unsafe { ptr::read_unaligned(p as *const u8) };
+ ControlMessageOwned::TlsGetRecordType(content_type.into())
+ },
(_, _) => {
- let sl = std::slice::from_raw_parts(p, len);
+ let sl = unsafe { std::slice::from_raw_parts(p, len) };
let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
ControlMessageOwned::Unknown(ucmsg)
}
}
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
#[cfg(feature = "net")]
#[allow(clippy::cast_ptr_alignment)] // False positive
unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
let ee = p as *const libc::sock_extended_err;
- let err = ptr::read_unaligned(ee);
+ let err = unsafe { ptr::read_unaligned(ee) };
// For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
// CMSG_DATA buffer. For local errors, there is no address included in the control
// message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer. So, we need to
// validate that the address object is in-bounds before we attempt to copy it.
- let addrp = libc::SO_EE_OFFENDER(ee) as *const T;
+ let addrp = unsafe { libc::SO_EE_OFFENDER(ee) as *const T };
- if addrp.offset(1) as usize - (p as usize) > len {
+ if unsafe { addrp.offset(1) } as usize - (p as usize) > len {
(err, None)
} else {
- (err, Some(ptr::read_unaligned(addrp)))
+ (err, Some(unsafe { ptr::read_unaligned(addrp) }))
}
}
}
-/// A type-safe zero-copy wrapper around a single control message, as used wih
-/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not
-/// exhaustively pattern-match it.
+/// A type-safe zero-copy wrapper around a single control message, as used with
+/// [`sendmsg`]. More types may be added to this enum; do not exhaustively
+/// pattern-match it.
///
/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -1074,8 +1039,7 @@ pub enum ControlMessage<'a> {
///
/// For further information, please refer to the
/// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
ScmCredentials(&'a UnixCredentials),
/// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
/// a process connected to the socket.
@@ -1089,41 +1053,28 @@ pub enum ControlMessage<'a> {
///
/// For further information, please refer to the
/// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(freebsdlike)]
ScmCreds,
/// Set IV for `AF_ALG` crypto API.
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetIv(&'a [u8]),
/// Set crypto operation for `AF_ALG` crypto API. It may be one of
/// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetOp(&'a libc::c_int),
/// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
/// for `AF_ALG` crypto API.
///
/// For further information, please refer to the
/// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(linux_android)]
AlgSetAeadAssoclen(&'a u32),
/// UDP GSO makes it possible for applications to generate network packets
@@ -1139,51 +1090,52 @@ pub enum ControlMessage<'a> {
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
UdpGsoSegments(&'a u16),
- /// Configure the sending addressing and interface for v4
+ /// Configure the sending addressing and interface for v4.
///
/// For further information, please refer to the
/// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4PacketInfo(&'a libc::in_pktinfo),
- /// Configure the sending addressing and interface for v6
+ /// Configure the sending addressing and interface for v6.
///
/// For further information, please refer to the
/// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
- #[cfg(any(target_os = "linux",
- target_os = "macos",
+ #[cfg(any(linux_android,
target_os = "netbsd",
target_os = "freebsd",
- target_os = "android",
- target_os = "ios",))]
+ apple_targets))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv6PacketInfo(&'a libc::in6_pktinfo),
/// Configure the IPv4 source address with `IP_SENDSRCADDR`.
- #[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- ))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Ipv4SendSrcAddr(&'a libc::in_addr),
+ /// Configure the hop limit for v6 multicast traffic.
+ ///
+ /// Set the IPv6 hop limit for this message. The argument is an integer
+ /// between 0 and 255. A value of -1 will set the hop limit to the route
+ /// default if possible on the interface. Without this cmsg, packets sent
+ /// with sendmsg have a hop limit of 1 and will not leave the local network.
+ /// For further information, please refer to the
+ /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ Ipv6HopLimit(&'a libc::c_int),
+
/// SO_RXQ_OVFL indicates that an unsigned 32 bit value
/// ancilliary msg (cmsg) should be attached to recieved
/// skbs indicating the number of packets dropped by the
/// socket between the last recieved packet and this
/// received packet.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
RxqOvfl(&'a u32),
/// Configure the transmission time of packets.
@@ -1227,18 +1179,18 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(fds) => {
fds as *const _ as *const u8
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(creds) => {
&creds.0 as *const libc::ucred as *const u8
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => {
// The kernel overwrites the data, we just zero it
// to make sure it's not uninitialized memory
unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
return
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(iv) => {
#[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
let af_alg_iv = libc::af_alg_iv {
@@ -1263,11 +1215,11 @@ impl<'a> ControlMessage<'a> {
return
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(op) => {
op as *const _ as *const u8
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(len) => {
len as *const _ as *const u8
},
@@ -1276,21 +1228,20 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(gso_size) => {
gso_size as *const _ as *const u8
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(drop_count) => {
drop_count as *const _ as *const u8
},
@@ -1314,23 +1265,23 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(fds) => {
mem::size_of_val(fds)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(creds) => {
mem::size_of_val(creds)
}
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => {
mem::size_of::<libc::cmsgcred>()
}
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(iv) => {
mem::size_of::<&[u8]>() + iv.len()
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(op) => {
mem::size_of_val(op)
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(len) => {
mem::size_of_val(len)
},
@@ -1339,21 +1290,22 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(gso_size) => {
mem::size_of_val(gso_size)
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(limit) => {
+ mem::size_of_val(limit)
+ },
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(drop_count) => {
mem::size_of_val(drop_count)
},
@@ -1368,31 +1320,30 @@ impl<'a> ControlMessage<'a> {
fn cmsg_level(&self) -> libc::c_int {
match *self {
ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
#[cfg(target_os = "linux")]
ControlMessage::TxTime(_) => libc::SOL_SOCKET,
@@ -1403,19 +1354,19 @@ impl<'a> ControlMessage<'a> {
fn cmsg_type(&self) -> libc::c_int {
match *self {
ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessage::ScmCreds => libc::SCM_CREDS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetIv(_) => {
libc::ALG_SET_IV
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetOp(_) => {
libc::ALG_SET_OP
},
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessage::AlgSetAeadAssoclen(_) => {
libc::ALG_SET_AEAD_ASSOCLEN
},
@@ -1424,21 +1375,20 @@ impl<'a> ControlMessage<'a> {
ControlMessage::UdpGsoSegments(_) => {
libc::UDP_SEGMENT
},
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
+ #[cfg(any(linux_android, target_os = "netbsd",
+ target_os = "freebsd", apple_targets))]
#[cfg(feature = "net")]
ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
+ #[cfg(any(freebsdlike, netbsdlike))]
#[cfg(feature = "net")]
ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
+ #[cfg(feature = "net")]
+ ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT,
+ #[cfg(any(linux_android, target_os = "fuchsia"))]
ControlMessage::RxqOvfl(_) => {
libc::SO_RXQ_OVFL
},
@@ -1452,10 +1402,12 @@ impl<'a> ControlMessage<'a> {
// Unsafe: cmsg must point to a valid cmsghdr with enough space to
// encode self.
unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
- (*cmsg).cmsg_level = self.cmsg_level();
- (*cmsg).cmsg_type = self.cmsg_type();
- (*cmsg).cmsg_len = self.cmsg_len();
- self.copy_to_cmsg_data(CMSG_DATA(cmsg));
+ unsafe {
+ (*cmsg).cmsg_level = self.cmsg_level();
+ (*cmsg).cmsg_type = self.cmsg_type();
+ (*cmsg).cmsg_len = self.cmsg_len();
+ self.copy_to_cmsg_data( CMSG_DATA(cmsg) );
+ }
}
}
@@ -1479,7 +1431,7 @@ impl<'a> ControlMessage<'a> {
/// let (r, w) = pipe().unwrap();
///
/// let iov = [IoSlice::new(b"hello")];
-/// let fds = [r];
+/// let fds = [r.as_raw_fd()];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
/// ```
@@ -1496,7 +1448,7 @@ impl<'a> ControlMessage<'a> {
/// let (r, w) = pipe().unwrap();
///
/// let iov = [IoSlice::new(b"hello")];
-/// let fds = [r];
+/// let fds = [r.as_raw_fd()];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
/// ```
@@ -1535,12 +1487,7 @@ pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
///
/// # References
/// [`sendmsg`](fn.sendmsg.html)
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
pub fn sendmmsg<'a, XS, AS, C, I, S>(
fd: RawFd,
data: &'a mut MultiHeaders<S>,
@@ -1556,7 +1503,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
AS: AsRef<[Option<S>]>,
I: AsRef<[IoSlice<'a>]> + 'a,
C: AsRef<[ControlMessage<'a>]> + 'a,
- S: SockaddrLike + 'a
+ S: SockaddrLike + 'a,
{
let mut count = 0;
@@ -1564,11 +1511,11 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
let p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
+ p.msg_iov = slice.as_ref().as_ptr().cast_mut().cast();
p.msg_iovlen = slice.as_ref().len() as _;
p.msg_namelen = addr.as_ref().map_or(0, S::len);
- p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr) as _;
+ p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr).cast_mut().cast();
// Encode each cmsg. This must happen after initializing the header because
// CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
@@ -1583,9 +1530,16 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
}
- count = i+1;
+ // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
+ // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
+ // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
+ // other words: `count` doesn't overflow
+ count = i + 1;
}
+ // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
+ // maximum number of messages that can be sent safely (i.e. `count` is the minimum of the sizes of `slices`,
+ // `data.items` and `addrs`)
let sent = Errno::result(unsafe {
libc::sendmmsg(
fd,
@@ -1604,12 +1558,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[derive(Debug)]
/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
pub struct MultiHeaders<S> {
@@ -1622,12 +1571,7 @@ pub struct MultiHeaders<S> {
msg_controllen: usize,
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
impl<S> MultiHeaders<S> {
/// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
///
@@ -1652,7 +1596,7 @@ impl<S> MultiHeaders<S> {
.enumerate()
.map(|(ix, address)| {
let (ptr, cap) = match &mut cmsg_buffers {
- Some(v) => ((&mut v[ix * msg_controllen] as *mut u8), msg_controllen),
+ Some(v) => (&mut v[ix * msg_controllen] as *mut u8, msg_controllen),
None => (std::ptr::null_mut(), 0),
};
let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) };
@@ -1697,12 +1641,7 @@ impl<S> MultiHeaders<S> {
// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
// details
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
pub fn recvmmsg<'a, XS, S, I>(
fd: RawFd,
data: &'a mut MultiHeaders<S>,
@@ -1711,14 +1650,19 @@ pub fn recvmmsg<'a, XS, S, I>(
mut timeout: Option<crate::sys::time::TimeSpec>,
) -> crate::Result<MultiResults<'a, S>>
where
- XS: IntoIterator<Item = &'a I>,
- I: AsRef<[IoSliceMut<'a>]> + 'a,
+ XS: IntoIterator<Item = &'a mut I>,
+ I: AsMut<[IoSliceMut<'a>]> + 'a,
{
let mut count = 0;
for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
let p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
- p.msg_iovlen = slice.as_ref().len() as _;
+ p.msg_iov = slice.as_mut().as_mut_ptr().cast();
+ p.msg_iovlen = slice.as_mut().len() as _;
+
+ // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
+ // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
+ // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
+ // other words: `count` doesn't overflow
count = i + 1;
}
@@ -1726,6 +1670,8 @@ where
.as_mut()
.map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
+ // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
+ // maximum number of messages that can be received safely (i.e. `count` is the minimum of the sizes of `slices` and `data.items`)
let received = Errno::result(unsafe {
libc::recvmmsg(
fd,
@@ -1743,16 +1689,9 @@ where
})
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
-///
-///
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
+#[derive(Debug)]
pub struct MultiResults<'a, S> {
// preallocated structures
rmm: &'a MultiHeaders<S>,
@@ -1760,12 +1699,7 @@ pub struct MultiResults<'a, S> {
received: usize,
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
impl<'a, S> Iterator for MultiResults<'a, S>
where
S: Copy + SockaddrLike,
@@ -1838,108 +1772,6 @@ impl<'a> Iterator for IoSliceIterator<'a> {
}
}
-// test contains both recvmmsg and timestaping which is linux only
-// there are existing tests for recvmmsg only in tests/
-#[cfg(target_os = "linux")]
-#[cfg(test)]
-mod test {
- use crate::sys::socket::{AddressFamily, ControlMessageOwned};
- use crate::*;
- use std::str::FromStr;
- use std::os::unix::io::AsRawFd;
-
- #[cfg_attr(qemu, ignore)]
- #[test]
- fn test_recvmm2() -> crate::Result<()> {
- use crate::sys::socket::{
- sendmsg, setsockopt, socket, sockopt::Timestamping, MsgFlags, SockFlag, SockType,
- SockaddrIn, TimestampingFlag,
- };
- use std::io::{IoSlice, IoSliceMut};
-
- let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
-
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- )?;
-
- let rsock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::SOCK_NONBLOCK,
- None,
- )?;
-
- crate::sys::socket::bind(rsock.as_raw_fd(), &sock_addr)?;
-
- setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
-
- let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
-
- let mut recv_buf = vec![0; 1024];
-
- let mut recv_iovs = Vec::new();
- let mut pkt_iovs = Vec::new();
-
- for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
- pkt_iovs.push(IoSliceMut::new(chunk));
- if ix % 2 == 1 {
- recv_iovs.push(pkt_iovs);
- pkt_iovs = Vec::new();
- }
- }
- drop(pkt_iovs);
-
- let flags = MsgFlags::empty();
- let iov1 = [IoSlice::new(&sbuf)];
-
- let cmsg = cmsg_space!(crate::sys::socket::Timestamps);
- sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
-
- let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
-
- let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10));
-
- let recv = super::recvmmsg(rsock.as_raw_fd(), &mut data, recv_iovs.iter(), flags, Some(t))?;
-
- for rmsg in recv {
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- let mut saw_time = false;
- let mut recvd = 0;
- for cmsg in rmsg.cmsgs() {
- if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
- let ts = timestamps.system;
-
- let sys_time =
- crate::time::clock_gettime(crate::time::ClockId::CLOCK_REALTIME)?;
- let diff = if ts > sys_time {
- ts - sys_time
- } else {
- sys_time - ts
- };
- assert!(std::time::Duration::from(diff).as_secs() < 60);
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- {
- saw_time = true;
- }
- }
- }
-
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- assert!(saw_time);
-
- for iov in rmsg.iovs() {
- recvd += iov.len();
- }
- assert_eq!(recvd, 400);
- }
-
- Ok(())
- }
-}
unsafe fn read_mhdr<'a, 'i, S>(
mhdr: msghdr,
r: isize,
@@ -1951,19 +1783,23 @@ unsafe fn read_mhdr<'a, 'i, S>(
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
let cmsghdr = {
- if mhdr.msg_controllen > 0 {
+ let ptr = if mhdr.msg_controllen > 0 {
debug_assert!(!mhdr.msg_control.is_null());
debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
- CMSG_FIRSTHDR(&mhdr as *const msghdr)
+ unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) }
} else {
ptr::null()
- }.as_ref()
+ };
+
+ unsafe {
+ ptr.as_ref()
+ }
};
// Ignore errors if this socket address has statically-known length
//
// This is to ensure that unix socket addresses have their length set appropriately.
- let _ = address.set_length(mhdr.msg_namelen as usize);
+ let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) };
RecvMsg {
bytes: r as usize,
@@ -2000,14 +1836,16 @@ unsafe fn pack_mhdr_to_receive<S>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = address as *mut c_void;
- (*p).msg_namelen = S::size();
- (*p).msg_iov = iov_buffer as *mut iovec;
- (*p).msg_iovlen = iov_buffer_len as _;
- (*p).msg_control = cmsg_buffer as *mut c_void;
- (*p).msg_controllen = cmsg_capacity as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
+ unsafe {
+ (*p).msg_name = address as *mut c_void;
+ (*p).msg_namelen = S::size();
+ (*p).msg_iov = iov_buffer as *mut iovec;
+ (*p).msg_iovlen = iov_buffer_len as _;
+ (*p).msg_control = cmsg_buffer as *mut c_void;
+ (*p).msg_controllen = cmsg_capacity as _;
+ (*p).msg_flags = 0;
+ mhdr.assume_init()
+ }
}
fn pack_mhdr_to_send<'a, I, C, S>(
@@ -2025,7 +1863,7 @@ fn pack_mhdr_to_send<'a, I, C, S>(
// The message header must be initialized before the individual cmsgs.
let cmsg_ptr = if capacity > 0 {
- cmsg_buffer.as_mut_ptr() as *mut c_void
+ cmsg_buffer.as_mut_ptr().cast()
} else {
ptr::null_mut()
};
@@ -2035,11 +1873,11 @@ fn pack_mhdr_to_send<'a, I, C, S>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
- (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()) as *mut _;
+ (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()).cast_mut().cast();
(*p).msg_namelen = addr.map(S::len).unwrap_or(0);
// transmute iov into a mutable pointer. sendmsg doesn't really mutate
// the buffer, but the standard says that it takes a mutable pointer
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
+ (*p).msg_iov = iov.as_ref().as_ptr().cast_mut().cast();
(*p).msg_iovlen = iov.as_ref().len() as _;
(*p).msg_control = cmsg_ptr;
(*p).msg_controllen = capacity as _;
@@ -2166,17 +2004,51 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(
Errno::result(res)?;
// Safe because socketpair returned success.
- unsafe {
- Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1])))
+ unsafe { Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Backlog(i32);
+
+impl Backlog {
+ /// Sets the listen queue size to system `SOMAXCONN` value
+ pub const MAXCONN: Self = Self(libc::SOMAXCONN);
+ /// Sets the listen queue size to -1 for system supporting it
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
+ pub const MAXALLOWABLE: Self = Self(-1);
+
+ /// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.
+ pub fn new<I: Into<i32>>(val: I) -> Result<Self> {
+ cfg_if! {
+ if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
+ const MIN: i32 = -1;
+ } else {
+ const MIN: i32 = 0;
+ }
+ }
+
+ let val = val.into();
+
+ if !(MIN..Self::MAXCONN.0).contains(&val) {
+ return Err(Errno::EINVAL);
+ }
+
+ Ok(Self(val))
+ }
+}
+
+impl From<Backlog> for i32 {
+ fn from(backlog: Backlog) -> Self {
+ backlog.0
}
}
/// Listen for connections on a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
-pub fn listen<F: AsFd>(sock: &F, backlog: usize) -> Result<()> {
+pub fn listen<F: AsFd>(sock: &F, backlog: Backlog) -> Result<()> {
let fd = sock.as_fd().as_raw_fd();
- let res = unsafe { libc::listen(fd, backlog as c_int) };
+ let res = unsafe { libc::listen(fd, backlog.into()) };
Errno::result(res).map(drop)
}
@@ -2211,14 +2083,12 @@ pub fn accept(sockfd: RawFd) -> Result<RawFd> {
target_arch = "x86_64"
)
),
- target_os = "dragonfly",
+ freebsdlike,
+ netbsdlike,
target_os = "emscripten",
- target_os = "freebsd",
target_os = "fuchsia",
- target_os = "illumos",
+ solarish,
target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"
))]
pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
let res = unsafe {
@@ -2245,7 +2115,7 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
unsafe {
let ret = libc::recv(
sockfd,
- buf.as_mut_ptr() as *mut c_void,
+ buf.as_mut_ptr().cast(),
buf.len() as size_t,
flags.bits(),
);
@@ -2269,20 +2139,14 @@ pub fn recvfrom<T: SockaddrLike>(
let ret = Errno::result(libc::recvfrom(
sockfd,
- buf.as_mut_ptr() as *mut c_void,
+ buf.as_mut_ptr().cast(),
buf.len() as size_t,
0,
- addr.as_mut_ptr() as *mut sockaddr,
+ addr.as_mut_ptr().cast(),
&mut len as *mut socklen_t,
))? as usize;
- Ok((
- ret,
- T::from_raw(
- addr.assume_init().as_ptr(),
- Some(len),
- ),
- ))
+ Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len))))
}
}
@@ -2298,7 +2162,7 @@ pub fn sendto(
let ret = unsafe {
libc::sendto(
fd,
- buf.as_ptr() as *const c_void,
+ buf.as_ptr().cast(),
buf.len() as size_t,
flags.bits(),
addr.as_ptr(),
@@ -2314,12 +2178,7 @@ pub fn sendto(
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
- libc::send(
- fd,
- buf.as_ptr() as *const c_void,
- buf.len() as size_t,
- flags.bits(),
- )
+ libc::send(fd, buf.as_ptr().cast(), buf.len() as size_t, flags.bits())
};
Errno::result(ret).map(|r| r as usize)
@@ -2386,8 +2245,7 @@ pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
- let ret =
- libc::getpeername(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
+ let ret = libc::getpeername(fd, addr.as_mut_ptr().cast(), &mut len);
Errno::result(ret)?;
@@ -2403,8 +2261,7 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
- let ret =
- libc::getsockname(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
+ let ret = libc::getsockname(fd, addr.as_mut_ptr().cast(), &mut len);
Errno::result(ret)?;
@@ -2439,27 +2296,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
}
}
-#[cfg(test)]
-mod tests {
- #[cfg(not(target_os = "redox"))]
- #[test]
- fn can_use_cmsg_space() {
- let _ = cmsg_space!(u8);
- }
-
- #[cfg(not(any(
- target_os = "redox",
- target_os = "linux",
- target_os = "android"
- )))]
- #[test]
- fn can_open_routing_socket() {
- let _ = super::socket(
- super::AddressFamily::Route,
- super::SockType::Raw,
- super::SockFlag::empty(),
- None,
- )
- .expect("Failed to open routing socket");
- }
-}