linux_io/
socket.rs

1/// Address types for the IPv4 and IPv6 protocol families.
2pub mod ip;
3
4use core::mem::size_of;
5
6pub use linux_unsafe::sock_type;
7
8use crate::fd::ioctl::{ioctl_read, IoctlReqRead, _IOR};
9
10/// A trait implemented by all socket address types.
11///
12/// **Safety:**
13/// - Implementers must ensure that the two raw methods always return
14/// valid pointers and lengths for the kernel to refer to. The pointers should
15/// always be to a sockaddr-shaped structure, which always starts with
16/// an `sa_family_t` field describing the protocol family that the address
17/// belongs to.
18/// - Both methods must return a pointer to the same memory so that writes
19/// through the mut pointer will be visible to reads through the const pointer.
20pub unsafe trait SockAddr {
21    /// Returns a raw const pointer and the length of what it points to for
22    /// use when sending a socket address to the kernel.
23    ///
24    /// **Safety:** Caller must ensure that `self` remains valid throughout
25    /// all use of the returned pointer and that use of it is consistent
26    /// with a shared borrow.
27    unsafe fn sockaddr_raw_const(&self)
28        -> (*const linux_unsafe::sockaddr, linux_unsafe::socklen_t);
29
30    /// Returns a raw mut pointer and the length of what it points to for
31    /// use when retrieving a socket address from the kernel.
32    ///
33    /// **Safety:** Caller must ensure that `self` remains valid throughout
34    /// all use of the returned pointer and that use of it is consistent
35    /// with a mutable borrow.
36    unsafe fn sockaddr_raw_mut(&mut self)
37        -> (*mut linux_unsafe::sockaddr, linux_unsafe::socklen_t);
38}
39
40/// Represents a socket protocol that is compatible with sockets belonging to
41/// the domain/family `FAMILY`.
42///
43/// This trait allows [`super::File::socket`] to return a file of the
44/// appropriate device type for the selected protocol so that the relevant
45/// socket `ioctl` requests will be supported on its result.
46pub trait SocketProtocol {
47    type Device: crate::fd::ioctl::IoDevice;
48
49    fn raw_protocol_num(&self) -> linux_unsafe::int;
50}
51
52/// Builds a reasonable default implementation of [`SocketProtocol`] with
53/// a fixed protocol number and device type.
54///
55/// **Safety:** Caller must ensure that the specified device marker type
56/// is suitable for the type of socket the kernel will return when requesting
57/// this protocol. This works in conjunction with the safety rules for
58/// implementing ioctl requests on device types; the designated device should
59/// only have ioctl request constants that can be called against a file
60/// descriptor of this protocol without the risk of memory corruption caused
61/// by an incorrect argument type.
62#[inline(always)]
63pub const unsafe fn socket_protocol<Device: crate::fd::ioctl::IoDevice>(
64    num: linux_unsafe::int,
65) -> SocketProtocolFixed<Device> {
66    SocketProtocolFixed::numbered(num)
67}
68
69/// A reasonable default implementation of [`SocketProtocol`] with a fixed
70/// protocol number and device type.
71///
72/// This is the return type of [`socket_protocol`].
73#[repr(transparent)]
74pub struct SocketProtocolFixed<Device: crate::fd::ioctl::IoDevice> {
75    num: linux_unsafe::int,
76    _phantom: core::marker::PhantomData<Device>,
77}
78
79/// A convenience implementation of [`SocketProtocol`] for simple protocols
80/// that belong to only a single family and have a fixed protocol number.
81impl<Device: crate::fd::ioctl::IoDevice> SocketProtocolFixed<Device> {
82    #[inline(always)]
83    pub(crate) const unsafe fn numbered(num: linux_unsafe::int) -> Self {
84        // The value of a `SocketProtocolFixed` is always just its protocol
85        // number directly, making it have identical layout to the raw
86        // protocol argument on the `socket` system call.
87        Self {
88            num,
89            _phantom: core::marker::PhantomData,
90        }
91    }
92}
93
94impl<Device: crate::fd::ioctl::IoDevice> SocketProtocol for SocketProtocolFixed<Device> {
95    type Device = Device;
96
97    #[inline(always)]
98    fn raw_protocol_num(&self) -> linux_unsafe::int {
99        self.num
100    }
101}
102
103/// Device type marker for [`crate::File`] instances that represent sockets.
104///
105/// In practice there should not typically be a `File<SocketDevice>` directly,
106/// but instead should use a protocol-specific device type that also has a
107/// blanket impl to make all of the `SocketDevice` ioctl requests available
108/// too.
109pub struct SocketDevice;
110
111impl crate::fd::ioctl::IoDevice for SocketDevice {}
112
113const SOCK_IOC_TYPE: linux_unsafe::ulong = 0x89;
114
115/// `ioctl` request to retrieve a `struct timeval` with the receive timestamp
116/// of the last packet passed to the user.
117pub const SIOCGSTAMP: IoctlReqRead<SocketDevice, linux_unsafe::timeval> = unsafe {
118    ioctl_read(_IOR(
119        SOCK_IOC_TYPE,
120        0x06,
121        // This size is expressed in the kernel as sizeof(long long[2]), rather
122        // than as "struct timeval".
123        (size_of::<core::ffi::c_longlong>() * 2) as linux_unsafe::ulong,
124    ))
125};