1 //! Socket interface functions
2 //!
3 //! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
4 use cfg_if::cfg_if;
5 use crate::{Error, Result, errno::Errno};
6 use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
7         CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
8 use memoffset::offset_of;
9 use std::{mem, ptr, slice};
10 use std::os::unix::io::RawFd;
11 #[cfg(all(target_os = "linux"))]
12 use crate::sys::time::TimeSpec;
13 use crate::sys::time::TimeVal;
14 use crate::sys::uio::IoVec;
15 
16 mod addr;
17 pub mod sockopt;
18 
19 /*
20  *
21  * ===== Re-exports =====
22  *
23  */
24 
25 #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
26 pub use self::addr::{
27     AddressFamily,
28     SockAddr,
29     InetAddr,
30     UnixAddr,
31     IpAddr,
32     Ipv4Addr,
33     Ipv6Addr,
34     LinkAddr,
35 };
36 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
37 pub use self::addr::{
38     AddressFamily,
39     SockAddr,
40     InetAddr,
41     UnixAddr,
42     IpAddr,
43     Ipv4Addr,
44     Ipv6Addr,
45 };
46 
47 #[cfg(any(target_os = "android", target_os = "linux"))]
48 pub use crate::sys::socket::addr::netlink::NetlinkAddr;
49 #[cfg(any(target_os = "android", target_os = "linux"))]
50 pub use crate::sys::socket::addr::alg::AlgAddr;
51 #[cfg(any(target_os = "android", target_os = "linux"))]
52 pub use crate::sys::socket::addr::vsock::VsockAddr;
53 
54 pub use libc::{
55     cmsghdr,
56     msghdr,
57     sa_family_t,
58     sockaddr,
59     sockaddr_in,
60     sockaddr_in6,
61     sockaddr_storage,
62     sockaddr_un,
63 };
64 
65 // Needed by the cmsg_space macro
66 #[doc(hidden)]
67 pub use libc::{c_uint, CMSG_SPACE};
68 
69 /// These constants are used to specify the communication semantics
70 /// when creating a socket with [`socket()`](fn.socket.html)
71 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
72 #[repr(i32)]
73 pub enum SockType {
74     /// Provides sequenced, reliable, two-way, connection-
75     /// based byte streams.  An out-of-band data transmission
76     /// mechanism may be supported.
77     Stream = libc::SOCK_STREAM,
78     /// Supports datagrams (connectionless, unreliable
79     /// messages of a fixed maximum length).
80     Datagram = libc::SOCK_DGRAM,
81     /// Provides a sequenced, reliable, two-way connection-
82     /// based data transmission path for datagrams of fixed
83     /// maximum length; a consumer is required to read an
84     /// entire packet with each input system call.
85     SeqPacket = libc::SOCK_SEQPACKET,
86     /// Provides raw network protocol access.
87     Raw = libc::SOCK_RAW,
88     /// Provides a reliable datagram layer that does not
89     /// guarantee ordering.
90     Rdm = libc::SOCK_RDM,
91 }
92 
93 /// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
94 /// to specify the protocol to use.
95 #[repr(i32)]
96 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
97 pub enum SockProtocol {
98     /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
99     Tcp = libc::IPPROTO_TCP,
100     /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
101     Udp = libc::IPPROTO_UDP,
102     /// Allows applications and other KEXTs to be notified when certain kernel events occur
103     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
104     #[cfg(any(target_os = "ios", target_os = "macos"))]
105     KextEvent = libc::SYSPROTO_EVENT,
106     /// Allows applications to configure and control a KEXT
107     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
108     #[cfg(any(target_os = "ios", target_os = "macos"))]
109     KextControl = libc::SYSPROTO_CONTROL,
110     /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
111     // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
112     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
113     #[cfg(any(target_os = "android", target_os = "linux"))]
114     NetlinkRoute = libc::NETLINK_ROUTE,
115     /// Reserved for user-mode socket protocols
116     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
117     #[cfg(any(target_os = "android", target_os = "linux"))]
118     NetlinkUserSock = libc::NETLINK_USERSOCK,
119     /// Query information about sockets of various protocol families from the kernel
120     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
121     #[cfg(any(target_os = "android", target_os = "linux"))]
122     NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
123     /// SELinux event notifications.
124     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
125     #[cfg(any(target_os = "android", target_os = "linux"))]
126     NetlinkSELinux = libc::NETLINK_SELINUX,
127     /// Open-iSCSI
128     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
129     #[cfg(any(target_os = "android", target_os = "linux"))]
130     NetlinkISCSI = libc::NETLINK_ISCSI,
131     /// Auditing
132     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
133     #[cfg(any(target_os = "android", target_os = "linux"))]
134     NetlinkAudit = libc::NETLINK_AUDIT,
135     /// Access to FIB lookup from user space
136     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
137     #[cfg(any(target_os = "android", target_os = "linux"))]
138     NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
139     /// Netfilter subsystem
140     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
141     #[cfg(any(target_os = "android", target_os = "linux"))]
142     NetlinkNetFilter = libc::NETLINK_NETFILTER,
143     /// SCSI Transports
144     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
145     #[cfg(any(target_os = "android", target_os = "linux"))]
146     NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
147     /// Infiniband RDMA
148     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
149     #[cfg(any(target_os = "android", target_os = "linux"))]
150     NetlinkRDMA = libc::NETLINK_RDMA,
151     /// Transport IPv6 packets from netfilter to user space.  Used by ip6_queue kernel module.
152     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
153     #[cfg(any(target_os = "android", target_os = "linux"))]
154     NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
155     /// DECnet routing messages
156     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
157     #[cfg(any(target_os = "android", target_os = "linux"))]
158     NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
159     /// Kernel messages to user space
160     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
161     #[cfg(any(target_os = "android", target_os = "linux"))]
162     NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
163     /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
164     /// configuration of the kernel crypto API.
165     /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
166     #[cfg(any(target_os = "android", target_os = "linux"))]
167     NetlinkCrypto = libc::NETLINK_CRYPTO,
168 }
169 
170 libc_bitflags!{
171     /// Additional socket options
172     pub struct SockFlag: c_int {
173         /// Set non-blocking mode on the new socket
174         #[cfg(any(target_os = "android",
175                   target_os = "dragonfly",
176                   target_os = "freebsd",
177                   target_os = "illumos",
178                   target_os = "linux",
179                   target_os = "netbsd",
180                   target_os = "openbsd"))]
181         SOCK_NONBLOCK;
182         /// Set close-on-exec on the new descriptor
183         #[cfg(any(target_os = "android",
184                   target_os = "dragonfly",
185                   target_os = "freebsd",
186                   target_os = "illumos",
187                   target_os = "linux",
188                   target_os = "netbsd",
189                   target_os = "openbsd"))]
190         SOCK_CLOEXEC;
191         /// Return `EPIPE` instead of raising `SIGPIPE`
192         #[cfg(target_os = "netbsd")]
193         SOCK_NOSIGPIPE;
194         /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
195         /// to the DNS port (typically 53)
196         #[cfg(target_os = "openbsd")]
197         SOCK_DNS;
198     }
199 }
200 
201 libc_bitflags!{
202     /// Flags for send/recv and their relatives
203     pub struct MsgFlags: c_int {
204         /// Sends or requests out-of-band data on sockets that support this notion
205         /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
206         /// support out-of-band data.
207         MSG_OOB;
208         /// Peeks at an incoming message. The data is treated as unread and the next
209         /// [`recv()`](fn.recv.html)
210         /// or similar function shall still return this data.
211         MSG_PEEK;
212         /// Receive operation blocks until the full amount of data can be
213         /// returned. The function may return smaller amount of data if a signal
214         /// is caught, an error or disconnect occurs.
215         MSG_WAITALL;
216         /// Enables nonblocking operation; if the operation would block,
217         /// `EAGAIN` or `EWOULDBLOCK` is returned.  This provides similar
218         /// behavior to setting the `O_NONBLOCK` flag
219         /// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
220         /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
221         /// call option, whereas `O_NONBLOCK` is a setting on the open file
222         /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)),
223         /// which will affect all threads in
224         /// the calling process and as well as other processes that hold
225         /// file descriptors referring to the same open file description.
226         MSG_DONTWAIT;
227         /// Receive flags: Control Data was discarded (buffer too small)
228         MSG_CTRUNC;
229         /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
230         /// (since Linux 2.4.27/2.6.8),
231         /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
232         /// sockets: return the real length of the packet or datagram, even
233         /// when it was longer than the passed buffer. Not implemented for UNIX
234         /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
235         ///
236         /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
237         MSG_TRUNC;
238         /// Terminates a record (when this notion is supported, as for
239         /// sockets of type [`SeqPacket`](enum.SockType.html)).
240         MSG_EOR;
241         /// This flag specifies that queued errors should be received from
242         /// the socket error queue. (For more details, see
243         /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
244         #[cfg(any(target_os = "android", target_os = "linux"))]
245         MSG_ERRQUEUE;
246         /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
247         /// file descriptor using the `SCM_RIGHTS` operation (described in
248         /// [unix(7)](https://linux.die.net/man/7/unix)).
249         /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
250         /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
251         ///
252         /// Only used in [`recvmsg`](fn.recvmsg.html) function.
253         #[cfg(any(target_os = "android",
254                   target_os = "dragonfly",
255                   target_os = "freebsd",
256                   target_os = "linux",
257                   target_os = "netbsd",
258                   target_os = "openbsd"))]
259         MSG_CMSG_CLOEXEC;
260     }
261 }
262 
263 cfg_if! {
264     if #[cfg(any(target_os = "android", target_os = "linux"))] {
265         /// Unix credentials of the sending process.
266         ///
267         /// This struct is used with the `SO_PEERCRED` ancillary message
268         /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
269         #[repr(transparent)]
270         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
271         pub struct UnixCredentials(libc::ucred);
272 
273         impl UnixCredentials {
274             /// Creates a new instance with the credentials of the current process
275             pub fn new() -> Self {
276                 UnixCredentials(libc::ucred {
277                     pid: crate::unistd::getpid().as_raw(),
278                     uid: crate::unistd::getuid().as_raw(),
279                     gid: crate::unistd::getgid().as_raw(),
280                 })
281             }
282 
283             /// Returns the process identifier
284             pub fn pid(&self) -> libc::pid_t {
285                 self.0.pid
286             }
287 
288             /// Returns the user identifier
289             pub fn uid(&self) -> libc::uid_t {
290                 self.0.uid
291             }
292 
293             /// Returns the group identifier
294             pub fn gid(&self) -> libc::gid_t {
295                 self.0.gid
296             }
297         }
298 
299         impl Default for UnixCredentials {
300             fn default() -> Self {
301                 Self::new()
302             }
303         }
304 
305         impl From<libc::ucred> for UnixCredentials {
306             fn from(cred: libc::ucred) -> Self {
307                 UnixCredentials(cred)
308             }
309         }
310 
311         impl Into<libc::ucred> for UnixCredentials {
312             fn into(self) -> libc::ucred {
313                 self.0
314             }
315         }
316     } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
317         /// Unix credentials of the sending process.
318         ///
319         /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
320         #[repr(transparent)]
321         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
322         pub struct UnixCredentials(libc::cmsgcred);
323 
324         impl UnixCredentials {
325             /// Returns the process identifier
326             pub fn pid(&self) -> libc::pid_t {
327                 self.0.cmcred_pid
328             }
329 
330             /// Returns the real user identifier
331             pub fn uid(&self) -> libc::uid_t {
332                 self.0.cmcred_uid
333             }
334 
335             /// Returns the effective user identifier
336             pub fn euid(&self) -> libc::uid_t {
337                 self.0.cmcred_euid
338             }
339 
340             /// Returns the real group identifier
341             pub fn gid(&self) -> libc::gid_t {
342                 self.0.cmcred_gid
343             }
344 
345             /// Returns a list group identifiers (the first one being the effective GID)
346             pub fn groups(&self) -> &[libc::gid_t] {
347                 unsafe { slice::from_raw_parts(self.0.cmcred_groups.as_ptr() as *const libc::gid_t, self.0.cmcred_ngroups as _) }
348             }
349         }
350 
351         impl From<libc::cmsgcred> for UnixCredentials {
352             fn from(cred: libc::cmsgcred) -> Self {
353                 UnixCredentials(cred)
354             }
355         }
356     }
357 }
358 
359 /// Request for multicast socket operations
360 ///
361 /// This is a wrapper type around `ip_mreq`.
362 #[repr(transparent)]
363 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
364 pub struct IpMembershipRequest(libc::ip_mreq);
365 
366 impl IpMembershipRequest {
367     /// Instantiate a new `IpMembershipRequest`
368     ///
369     /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self370     pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
371         IpMembershipRequest(libc::ip_mreq {
372             imr_multiaddr: group.0,
373             imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
374         })
375     }
376 }
377 
378 /// Request for ipv6 multicast socket operations
379 ///
380 /// This is a wrapper type around `ipv6_mreq`.
381 #[repr(transparent)]
382 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
383 pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
384 
385 impl Ipv6MembershipRequest {
386     /// Instantiate a new `Ipv6MembershipRequest`
new(group: Ipv6Addr) -> Self387     pub fn new(group: Ipv6Addr) -> Self {
388         Ipv6MembershipRequest(libc::ipv6_mreq {
389             ipv6mr_multiaddr: group.0,
390             ipv6mr_interface: 0,
391         })
392     }
393 }
394 
395 /// Create a buffer large enough for storing some control messages as returned
396 /// by [`recvmsg`](fn.recvmsg.html).
397 ///
398 /// # Examples
399 ///
400 /// ```
401 /// # #[macro_use] extern crate nix;
402 /// # use nix::sys::time::TimeVal;
403 /// # use std::os::unix::io::RawFd;
404 /// # fn main() {
405 /// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
406 /// let _ = cmsg_space!(TimeVal);
407 /// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
408 /// // with two file descriptors
409 /// let _ = cmsg_space!([RawFd; 2]);
410 /// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
411 /// // and a `ControlMessageOwned::ScmTimestamp` message
412 /// let _ = cmsg_space!(RawFd, TimeVal);
413 /// # }
414 /// ```
415 // Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
416 // stack-allocated array.
417 #[macro_export]
418 macro_rules! cmsg_space {
419     ( $( $x:ty ),* ) => {
420         {
421             let mut space = 0;
422             $(
423                 // CMSG_SPACE is always safe
424                 space += unsafe {
425                     $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
426                 } as usize;
427             )*
428             Vec::<u8>::with_capacity(space)
429         }
430     }
431 }
432 
433 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
434 pub struct RecvMsg<'a> {
435     pub bytes: usize,
436     cmsghdr: Option<&'a cmsghdr>,
437     pub address: Option<SockAddr>,
438     pub flags: MsgFlags,
439     mhdr: msghdr,
440 }
441 
442 impl<'a> RecvMsg<'a> {
443     /// Iterate over the valid control messages pointed to by this
444     /// msghdr.
cmsgs(&self) -> CmsgIterator445     pub fn cmsgs(&self) -> CmsgIterator {
446         CmsgIterator {
447             cmsghdr: self.cmsghdr,
448             mhdr: &self.mhdr
449         }
450     }
451 }
452 
453 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
454 pub struct CmsgIterator<'a> {
455     /// Control message buffer to decode from. Must adhere to cmsg alignment.
456     cmsghdr: Option<&'a cmsghdr>,
457     mhdr: &'a msghdr
458 }
459 
460 impl<'a> Iterator for CmsgIterator<'a> {
461     type Item = ControlMessageOwned;
462 
next(&mut self) -> Option<ControlMessageOwned>463     fn next(&mut self) -> Option<ControlMessageOwned> {
464         match self.cmsghdr {
465             None => None,   // No more messages
466             Some(hdr) => {
467                 // Get the data.
468                 // Safe if cmsghdr points to valid data returned by recvmsg(2)
469                 let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
470                 // Advance the internal pointer.  Safe if mhdr and cmsghdr point
471                 // to valid data returned by recvmsg(2)
472                 self.cmsghdr = unsafe {
473                     let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
474                     p.as_ref()
475                 };
476                 cm
477             }
478         }
479     }
480 }
481 
482 /// A type-safe wrapper around a single control message, as used with
483 /// [`recvmsg`](#fn.recvmsg).
484 ///
485 /// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
486 //  Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
487 //  sendmsg.  However, on some platforms the messages returned by recvmsg may be
488 //  unaligned.  ControlMessageOwned takes those messages by copy, obviating any
489 //  alignment issues.
490 //
491 //  See https://github.com/nix-rust/nix/issues/999
492 #[derive(Clone, Debug, Eq, PartialEq)]
493 pub enum ControlMessageOwned {
494     /// Received version of
495     /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
496     ScmRights(Vec<RawFd>),
497     /// Received version of
498     /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
499     #[cfg(any(target_os = "android", target_os = "linux"))]
500     ScmCredentials(UnixCredentials),
501     /// Received version of
502     /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
503     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
504     ScmCreds(UnixCredentials),
505     /// A message of type `SCM_TIMESTAMP`, containing the time the
506     /// packet was received by the kernel.
507     ///
508     /// See the kernel's explanation in "SO_TIMESTAMP" of
509     /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
510     ///
511     /// # Examples
512     ///
513     /// ```
514     /// # #[macro_use] extern crate nix;
515     /// # use nix::sys::socket::*;
516     /// # use nix::sys::uio::IoVec;
517     /// # use nix::sys::time::*;
518     /// # use std::time::*;
519     /// # fn main() {
520     /// // Set up
521     /// let message = "Ohayō!".as_bytes();
522     /// let in_socket = socket(
523     ///     AddressFamily::Inet,
524     ///     SockType::Datagram,
525     ///     SockFlag::empty(),
526     ///     None).unwrap();
527     /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
528     /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
529     /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
530     /// let address = getsockname(in_socket).unwrap();
531     /// // Get initial time
532     /// let time0 = SystemTime::now();
533     /// // Send the message
534     /// let iov = [IoVec::from_slice(message)];
535     /// let flags = MsgFlags::empty();
536     /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
537     /// assert_eq!(message.len(), l);
538     /// // Receive the message
539     /// let mut buffer = vec![0u8; message.len()];
540     /// let mut cmsgspace = cmsg_space!(TimeVal);
541     /// let iov = [IoVec::from_mut_slice(&mut buffer)];
542     /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
543     /// let rtime = match r.cmsgs().next() {
544     ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
545     ///     Some(_) => panic!("Unexpected control message"),
546     ///     None => panic!("No control message")
547     /// };
548     /// // Check the final time
549     /// let time1 = SystemTime::now();
550     /// // the packet's received timestamp should lie in-between the two system
551     /// // times, unless the system clock was adjusted in the meantime.
552     /// let rduration = Duration::new(rtime.tv_sec() as u64,
553     ///                               rtime.tv_usec() as u32 * 1000);
554     /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
555     /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
556     /// // Close socket
557     /// nix::unistd::close(in_socket).unwrap();
558     /// # }
559     /// ```
560     ScmTimestamp(TimeVal),
561     /// Nanoseconds resolution timestamp
562     ///
563     /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
564     #[cfg(all(target_os = "linux"))]
565     ScmTimestampns(TimeSpec),
566     #[cfg(any(
567         target_os = "android",
568         target_os = "ios",
569         target_os = "linux",
570         target_os = "macos",
571         target_os = "netbsd",
572     ))]
573     Ipv4PacketInfo(libc::in_pktinfo),
574     #[cfg(any(
575         target_os = "android",
576         target_os = "dragonfly",
577         target_os = "freebsd",
578         target_os = "ios",
579         target_os = "linux",
580         target_os = "macos",
581         target_os = "openbsd",
582         target_os = "netbsd",
583     ))]
584     Ipv6PacketInfo(libc::in6_pktinfo),
585     #[cfg(any(
586         target_os = "freebsd",
587         target_os = "ios",
588         target_os = "macos",
589         target_os = "netbsd",
590         target_os = "openbsd",
591     ))]
592     Ipv4RecvIf(libc::sockaddr_dl),
593     #[cfg(any(
594         target_os = "freebsd",
595         target_os = "ios",
596         target_os = "macos",
597         target_os = "netbsd",
598         target_os = "openbsd",
599     ))]
600     Ipv4RecvDstAddr(libc::in_addr),
601 
602     /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
603     /// packets from a single sender.
604     /// Fixed-size payloads are following one by one in a receive buffer.
605     /// This Control Message indicates the size of all smaller packets,
606     /// except, maybe, the last one.
607     ///
608     /// `UdpGroSegment` socket option should be enabled on a socket
609     /// to allow receiving GRO packets.
610     #[cfg(target_os = "linux")]
611     UdpGroSegments(u16),
612 
613     /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
614     /// ancilliary msg (cmsg) should be attached to recieved
615     /// skbs indicating the number of packets dropped by the
616     /// socket between the last recieved packet and this
617     /// received packet.
618     ///
619     /// `RxqOvfl` socket option should be enabled on a socket
620     /// to allow receiving the drop counter.
621     #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
622     RxqOvfl(u32),
623 
624     /// Catch-all variant for unimplemented cmsg types.
625     #[doc(hidden)]
626     Unknown(UnknownCmsg),
627 }
628 
629 impl ControlMessageOwned {
630     /// Decodes a `ControlMessageOwned` from raw bytes.
631     ///
632     /// This is only safe to call if the data is correct for the message type
633     /// specified in the header. Normally, the kernel ensures that this is the
634     /// case. "Correct" in this case includes correct length, alignment and
635     /// actual content.
636     // Clippy complains about the pointer alignment of `p`, not understanding
637     // that it's being fed to a function that can handle that.
638     #[allow(clippy::cast_ptr_alignment)]
decode_from(header: &cmsghdr) -> ControlMessageOwned639     unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
640     {
641         let p = CMSG_DATA(header);
642         let len = header as *const _ as usize + header.cmsg_len as usize
643             - p as usize;
644         match (header.cmsg_level, header.cmsg_type) {
645             (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
646                 let n = len / mem::size_of::<RawFd>();
647                 let mut fds = Vec::with_capacity(n);
648                 for i in 0..n {
649                     let fdp = (p as *const RawFd).add(i);
650                     fds.push(ptr::read_unaligned(fdp));
651                 }
652                 ControlMessageOwned::ScmRights(fds)
653             },
654             #[cfg(any(target_os = "android", target_os = "linux"))]
655             (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
656                 let cred: libc::ucred = ptr::read_unaligned(p as *const _);
657                 ControlMessageOwned::ScmCredentials(cred.into())
658             }
659             #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
660             (libc::SOL_SOCKET, libc::SCM_CREDS) => {
661                 let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
662                 ControlMessageOwned::ScmCreds(cred.into())
663             }
664             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
665                 let tv: libc::timeval = ptr::read_unaligned(p as *const _);
666                 ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
667             },
668             #[cfg(all(target_os = "linux"))]
669             (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
670                 let ts: libc::timespec = ptr::read_unaligned(p as *const _);
671                 ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
672             }
673             #[cfg(any(
674                 target_os = "android",
675                 target_os = "freebsd",
676                 target_os = "ios",
677                 target_os = "linux",
678                 target_os = "macos"
679             ))]
680             (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
681                 let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
682                 ControlMessageOwned::Ipv6PacketInfo(info)
683             }
684             #[cfg(any(
685                 target_os = "android",
686                 target_os = "ios",
687                 target_os = "linux",
688                 target_os = "macos",
689                 target_os = "netbsd",
690             ))]
691             (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
692                 let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
693                 ControlMessageOwned::Ipv4PacketInfo(info)
694             }
695             #[cfg(any(
696                 target_os = "freebsd",
697                 target_os = "ios",
698                 target_os = "macos",
699                 target_os = "netbsd",
700                 target_os = "openbsd",
701             ))]
702             (libc::IPPROTO_IP, libc::IP_RECVIF) => {
703                 let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
704                 ControlMessageOwned::Ipv4RecvIf(dl)
705             },
706             #[cfg(any(
707                 target_os = "freebsd",
708                 target_os = "ios",
709                 target_os = "macos",
710                 target_os = "netbsd",
711                 target_os = "openbsd",
712             ))]
713             (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
714                 let dl = ptr::read_unaligned(p as *const libc::in_addr);
715                 ControlMessageOwned::Ipv4RecvDstAddr(dl)
716             },
717             #[cfg(target_os = "linux")]
718             (libc::SOL_UDP, libc::UDP_GRO) => {
719                 let gso_size: u16 = ptr::read_unaligned(p as *const _);
720                 ControlMessageOwned::UdpGroSegments(gso_size)
721             },
722             #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
723             (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
724                 let drop_counter = ptr::read_unaligned(p as *const u32);
725                 ControlMessageOwned::RxqOvfl(drop_counter)
726             },
727             (_, _) => {
728                 let sl = slice::from_raw_parts(p, len);
729                 let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
730                 ControlMessageOwned::Unknown(ucmsg)
731             }
732         }
733     }
734 }
735 
736 /// A type-safe zero-copy wrapper around a single control message, as used wih
737 /// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
738 /// exhaustively pattern-match it.
739 ///
740 /// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
741 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
742 pub enum ControlMessage<'a> {
743     /// A message of type `SCM_RIGHTS`, containing an array of file
744     /// descriptors passed between processes.
745     ///
746     /// See the description in the "Ancillary messages" section of the
747     /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
748     ///
749     /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
750     /// recommended since it causes platform-dependent behaviour: It might
751     /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
752     /// Instead, you can put all fds to be passed into a single `ScmRights`
753     /// message.
754     ScmRights(&'a [RawFd]),
755     /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
756     /// a process connected to the socket.
757     ///
758     /// This is similar to the socket option `SO_PEERCRED`, but requires a
759     /// process to explicitly send its credentials. A process running as root is
760     /// allowed to specify any credentials, while credentials sent by other
761     /// processes are verified by the kernel.
762     ///
763     /// For further information, please refer to the
764     /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
765     #[cfg(any(target_os = "android", target_os = "linux"))]
766     ScmCredentials(&'a UnixCredentials),
767     /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
768     /// a process connected to the socket.
769     ///
770     /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
771     /// requires a process to explicitly send its credentials.
772     ///
773     /// Credentials are always overwritten by the kernel, so this variant does have
774     /// any data, unlike the receive-side
775     /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
776     ///
777     /// For further information, please refer to the
778     /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
779     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
780     ScmCreds,
781 
782     /// Set IV for `AF_ALG` crypto API.
783     ///
784     /// For further information, please refer to the
785     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
786     #[cfg(any(
787         target_os = "android",
788         target_os = "linux",
789     ))]
790     AlgSetIv(&'a [u8]),
791     /// Set crypto operation for `AF_ALG` crypto API. It may be one of
792     /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
793     ///
794     /// For further information, please refer to the
795     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
796     #[cfg(any(
797         target_os = "android",
798         target_os = "linux",
799     ))]
800     AlgSetOp(&'a libc::c_int),
801     /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
802     /// for `AF_ALG` crypto API.
803     ///
804     /// For further information, please refer to the
805     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
806     #[cfg(any(
807         target_os = "android",
808         target_os = "linux",
809     ))]
810     AlgSetAeadAssoclen(&'a u32),
811 
812     /// UDP GSO makes it possible for applications to generate network packets
813     /// for a virtual MTU much greater than the real one.
814     /// The length of the send data no longer matches the expected length on
815     /// the wire.
816     /// The size of the datagram payload as it should appear on the wire may be
817     /// passed through this control message.
818     /// Send buffer should consist of multiple fixed-size wire payloads
819     /// following one by one, and the last, possibly smaller one.
820     #[cfg(target_os = "linux")]
821     UdpGsoSegments(&'a u16),
822 
823     /// Configure the sending addressing and interface for v4
824     ///
825     /// For further information, please refer to the
826     /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
827     #[cfg(any(target_os = "linux",
828               target_os = "macos",
829               target_os = "netbsd",
830               target_os = "android",
831               target_os = "ios",))]
832     Ipv4PacketInfo(&'a libc::in_pktinfo),
833 
834     /// Configure the sending addressing and interface for v6
835     ///
836     /// For further information, please refer to the
837     /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
838     #[cfg(any(target_os = "linux",
839               target_os = "macos",
840               target_os = "netbsd",
841               target_os = "freebsd",
842               target_os = "android",
843               target_os = "ios",))]
844     Ipv6PacketInfo(&'a libc::in6_pktinfo),
845 
846     /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
847     /// ancilliary msg (cmsg) should be attached to recieved
848     /// skbs indicating the number of packets dropped by the
849     /// socket between the last recieved packet and this
850     /// received packet.
851     #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
852     RxqOvfl(&'a u32),
853 }
854 
855 // An opaque structure used to prevent cmsghdr from being a public type
856 #[doc(hidden)]
857 #[derive(Clone, Debug, Eq, PartialEq)]
858 pub struct UnknownCmsg(cmsghdr, Vec<u8>);
859 
860 impl<'a> ControlMessage<'a> {
861     /// The value of CMSG_SPACE on this message.
862     /// Safe because CMSG_SPACE is always safe
space(&self) -> usize863     fn space(&self) -> usize {
864         unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
865     }
866 
867     /// The value of CMSG_LEN on this message.
868     /// Safe because CMSG_LEN is always safe
869     #[cfg(any(target_os = "android",
870               all(target_os = "linux", not(target_env = "musl"))))]
cmsg_len(&self) -> usize871     fn cmsg_len(&self) -> usize {
872         unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
873     }
874 
875     #[cfg(not(any(target_os = "android",
876                   all(target_os = "linux", not(target_env = "musl")))))]
cmsg_len(&self) -> libc::c_uint877     fn cmsg_len(&self) -> libc::c_uint {
878         unsafe{CMSG_LEN(self.len() as libc::c_uint)}
879     }
880 
881     /// Return a reference to the payload data as a byte pointer
copy_to_cmsg_data(&self, cmsg_data: *mut u8)882     fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
883         let data_ptr = match *self {
884             ControlMessage::ScmRights(fds) => {
885                 fds as *const _ as *const u8
886             },
887             #[cfg(any(target_os = "android", target_os = "linux"))]
888             ControlMessage::ScmCredentials(creds) => {
889                 &creds.0 as *const libc::ucred as *const u8
890             }
891             #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
892             ControlMessage::ScmCreds => {
893                 // The kernel overwrites the data, we just zero it
894                 // to make sure it's not uninitialized memory
895                 unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
896                 return
897             }
898             #[cfg(any(target_os = "android", target_os = "linux"))]
899             ControlMessage::AlgSetIv(iv) => {
900                 #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
901                 let af_alg_iv = libc::af_alg_iv {
902                     ivlen: iv.len() as u32,
903                     iv: [0u8; 0],
904                 };
905 
906                 let size = mem::size_of_val(&af_alg_iv);
907 
908                 unsafe {
909                     ptr::copy_nonoverlapping(
910                         &af_alg_iv as *const _ as *const u8,
911                         cmsg_data,
912                         size,
913                     );
914                     ptr::copy_nonoverlapping(
915                         iv.as_ptr(),
916                         cmsg_data.add(size),
917                         iv.len()
918                     );
919                 };
920 
921                 return
922             },
923             #[cfg(any(target_os = "android", target_os = "linux"))]
924             ControlMessage::AlgSetOp(op) => {
925                 op as *const _ as *const u8
926             },
927             #[cfg(any(target_os = "android", target_os = "linux"))]
928             ControlMessage::AlgSetAeadAssoclen(len) => {
929                 len as *const _ as *const u8
930             },
931             #[cfg(target_os = "linux")]
932             ControlMessage::UdpGsoSegments(gso_size) => {
933                 gso_size as *const _ as *const u8
934             },
935             #[cfg(any(target_os = "linux", target_os = "macos",
936                       target_os = "netbsd", target_os = "android",
937                       target_os = "ios",))]
938             ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
939             #[cfg(any(target_os = "linux", target_os = "macos",
940                       target_os = "netbsd", target_os = "freebsd",
941                       target_os = "android", target_os = "ios",))]
942             ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
943             #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
944             ControlMessage::RxqOvfl(drop_count) => {
945                 drop_count as *const _ as *const u8
946             },
947         };
948         unsafe {
949             ptr::copy_nonoverlapping(
950                 data_ptr,
951                 cmsg_data,
952                 self.len()
953             )
954         };
955     }
956 
957     /// The size of the payload, excluding its cmsghdr
len(&self) -> usize958     fn len(&self) -> usize {
959         match *self {
960             ControlMessage::ScmRights(fds) => {
961                 mem::size_of_val(fds)
962             },
963             #[cfg(any(target_os = "android", target_os = "linux"))]
964             ControlMessage::ScmCredentials(creds) => {
965                 mem::size_of_val(creds)
966             }
967             #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
968             ControlMessage::ScmCreds => {
969                 mem::size_of::<libc::cmsgcred>()
970             }
971             #[cfg(any(target_os = "android", target_os = "linux"))]
972             ControlMessage::AlgSetIv(iv) => {
973                 mem::size_of_val(&iv) + iv.len()
974             },
975             #[cfg(any(target_os = "android", target_os = "linux"))]
976             ControlMessage::AlgSetOp(op) => {
977                 mem::size_of_val(op)
978             },
979             #[cfg(any(target_os = "android", target_os = "linux"))]
980             ControlMessage::AlgSetAeadAssoclen(len) => {
981                 mem::size_of_val(len)
982             },
983             #[cfg(target_os = "linux")]
984             ControlMessage::UdpGsoSegments(gso_size) => {
985                 mem::size_of_val(gso_size)
986             },
987             #[cfg(any(target_os = "linux", target_os = "macos",
988               target_os = "netbsd", target_os = "android",
989               target_os = "ios",))]
990             ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
991             #[cfg(any(target_os = "linux", target_os = "macos",
992               target_os = "netbsd", target_os = "freebsd",
993               target_os = "android", target_os = "ios",))]
994             ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
995             #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
996             ControlMessage::RxqOvfl(drop_count) => {
997                 mem::size_of_val(drop_count)
998             },
999         }
1000     }
1001 
1002     /// Returns the value to put into the `cmsg_level` field of the header.
cmsg_level(&self) -> libc::c_int1003     fn cmsg_level(&self) -> libc::c_int {
1004         match *self {
1005             ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
1006             #[cfg(any(target_os = "android", target_os = "linux"))]
1007             ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
1008             #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
1009             ControlMessage::ScmCreds => libc::SOL_SOCKET,
1010             #[cfg(any(target_os = "android", target_os = "linux"))]
1011             ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
1012                 ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
1013             #[cfg(target_os = "linux")]
1014             ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
1015             #[cfg(any(target_os = "linux", target_os = "macos",
1016                       target_os = "netbsd", target_os = "android",
1017                       target_os = "ios",))]
1018             ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
1019             #[cfg(any(target_os = "linux", target_os = "macos",
1020               target_os = "netbsd", target_os = "freebsd",
1021               target_os = "android", target_os = "ios",))]
1022             ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
1023             #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
1024             ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
1025         }
1026     }
1027 
1028     /// Returns the value to put into the `cmsg_type` field of the header.
cmsg_type(&self) -> libc::c_int1029     fn cmsg_type(&self) -> libc::c_int {
1030         match *self {
1031             ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
1032             #[cfg(any(target_os = "android", target_os = "linux"))]
1033             ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
1034             #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
1035             ControlMessage::ScmCreds => libc::SCM_CREDS,
1036             #[cfg(any(target_os = "android", target_os = "linux"))]
1037             ControlMessage::AlgSetIv(_) => {
1038                 libc::ALG_SET_IV
1039             },
1040             #[cfg(any(target_os = "android", target_os = "linux"))]
1041             ControlMessage::AlgSetOp(_) => {
1042                 libc::ALG_SET_OP
1043             },
1044             #[cfg(any(target_os = "android", target_os = "linux"))]
1045             ControlMessage::AlgSetAeadAssoclen(_) => {
1046                 libc::ALG_SET_AEAD_ASSOCLEN
1047             },
1048             #[cfg(target_os = "linux")]
1049             ControlMessage::UdpGsoSegments(_) => {
1050                 libc::UDP_SEGMENT
1051             },
1052             #[cfg(any(target_os = "linux", target_os = "macos",
1053                       target_os = "netbsd", target_os = "android",
1054                       target_os = "ios",))]
1055             ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
1056             #[cfg(any(target_os = "linux", target_os = "macos",
1057                       target_os = "netbsd", target_os = "freebsd",
1058                       target_os = "android", target_os = "ios",))]
1059             ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
1060             #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
1061             ControlMessage::RxqOvfl(_) => {
1062                 libc::SO_RXQ_OVFL
1063             },
1064         }
1065     }
1066 
1067     // Unsafe: cmsg must point to a valid cmsghdr with enough space to
1068     // encode self.
encode_into(&self, cmsg: *mut cmsghdr)1069     unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
1070         (*cmsg).cmsg_level = self.cmsg_level();
1071         (*cmsg).cmsg_type = self.cmsg_type();
1072         (*cmsg).cmsg_len = self.cmsg_len();
1073         self.copy_to_cmsg_data(CMSG_DATA(cmsg));
1074     }
1075 }
1076 
1077 
1078 /// Send data in scatter-gather vectors to a socket, possibly accompanied
1079 /// by ancillary data. Optionally direct the message at the given address,
1080 /// as with sendto.
1081 ///
1082 /// Allocates if cmsgs is nonempty.
sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>1083 pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
1084                flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
1085 {
1086     let capacity = cmsgs.iter().map(|c| c.space()).sum();
1087 
1088     // First size the buffer needed to hold the cmsgs.  It must be zeroed,
1089     // because subsequent code will not clear the padding bytes.
1090     let mut cmsg_buffer = vec![0u8; capacity];
1091 
1092     let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr);
1093 
1094     let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
1095 
1096     Errno::result(ret).map(|r| r as usize)
1097 }
1098 
1099 #[cfg(any(
1100     target_os = "linux",
1101     target_os = "android",
1102     target_os = "freebsd",
1103     target_os = "netbsd",
1104 ))]
1105 #[derive(Debug)]
1106 pub struct SendMmsgData<'a, I, C>
1107     where
1108         I: AsRef<[IoVec<&'a [u8]>]>,
1109         C: AsRef<[ControlMessage<'a>]>
1110 {
1111     pub iov: I,
1112     pub cmsgs: C,
1113     pub addr: Option<SockAddr>,
1114     pub _lt: std::marker::PhantomData<&'a I>,
1115 }
1116 
1117 /// An extension of `sendmsg` that allows the caller to transmit multiple
1118 /// messages on a socket using a single system call. This has performance
1119 /// benefits for some applications.
1120 ///
1121 /// Allocations are performed for cmsgs and to build `msghdr` buffer
1122 ///
1123 /// # Arguments
1124 ///
1125 /// * `fd`:             Socket file descriptor
1126 /// * `data`:           Struct that implements `IntoIterator` with `SendMmsgData` items
1127 /// * `flags`:          Optional flags passed directly to the operating system.
1128 ///
1129 /// # Returns
1130 /// `Vec` with numbers of sent bytes on each sent message.
1131 ///
1132 /// # References
1133 /// [`sendmsg`](fn.sendmsg.html)
1134 #[cfg(any(
1135     target_os = "linux",
1136     target_os = "android",
1137     target_os = "freebsd",
1138     target_os = "netbsd",
1139 ))]
sendmmsg<'a, I, C>( fd: RawFd, data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>, flags: MsgFlags ) -> Result<Vec<usize>> where I: AsRef<[IoVec<&'a [u8]>]> + 'a, C: AsRef<[ControlMessage<'a>]> + 'a,1140 pub fn sendmmsg<'a, I, C>(
1141     fd: RawFd,
1142     data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
1143     flags: MsgFlags
1144 ) -> Result<Vec<usize>>
1145     where
1146         I: AsRef<[IoVec<&'a [u8]>]> + 'a,
1147         C: AsRef<[ControlMessage<'a>]> + 'a,
1148 {
1149     let iter = data.into_iter();
1150 
1151     let size_hint = iter.size_hint();
1152     let reserve_items = size_hint.1.unwrap_or(size_hint.0);
1153 
1154     let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
1155 
1156     let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);
1157 
1158     for d in iter {
1159         let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
1160         let mut cmsgs_buffer = vec![0u8; capacity];
1161 
1162         output.push(libc::mmsghdr {
1163             msg_hdr: pack_mhdr_to_send(
1164                 &mut cmsgs_buffer,
1165                 &d.iov,
1166                 &d.cmsgs,
1167                 d.addr.as_ref()
1168             ),
1169             msg_len: 0,
1170         });
1171         cmsgs_buffers.push(cmsgs_buffer);
1172     };
1173 
1174     let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
1175 
1176     let sent_messages = Errno::result(ret)? as usize;
1177     let mut sent_bytes = Vec::with_capacity(sent_messages);
1178 
1179     for item in &output {
1180         sent_bytes.push(item.msg_len as usize);
1181     }
1182 
1183     Ok(sent_bytes)
1184 }
1185 
1186 
1187 #[cfg(any(
1188     target_os = "linux",
1189     target_os = "android",
1190     target_os = "freebsd",
1191     target_os = "netbsd",
1192 ))]
1193 #[derive(Debug)]
1194 pub struct RecvMmsgData<'a, I>
1195     where
1196         I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
1197 {
1198     pub iov: I,
1199     pub cmsg_buffer: Option<&'a mut Vec<u8>>,
1200 }
1201 
1202 /// An extension of `recvmsg` that allows the caller to receive multiple
1203 /// messages from a socket using a single system call. This has
1204 /// performance benefits for some applications.
1205 ///
1206 /// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg`
1207 ///
1208 /// Multiple allocations are performed
1209 ///
1210 /// # Arguments
1211 ///
1212 /// * `fd`:             Socket file descriptor
1213 /// * `data`:           Struct that implements `IntoIterator` with `RecvMmsgData` items
1214 /// * `flags`:          Optional flags passed directly to the operating system.
1215 ///
1216 /// # RecvMmsgData
1217 ///
1218 /// * `iov`:            Scatter-gather list of buffers to receive the message
1219 /// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
1220 ///                     [`cmsg_space!`](macro.cmsg_space.html)
1221 ///
1222 /// # Returns
1223 /// A `Vec` with multiple `RecvMsg`, one per received message
1224 ///
1225 /// # References
1226 /// - [`recvmsg`](fn.recvmsg.html)
1227 /// - [`RecvMsg`](struct.RecvMsg.html)
1228 #[cfg(any(
1229     target_os = "linux",
1230     target_os = "android",
1231     target_os = "freebsd",
1232     target_os = "netbsd",
1233 ))]
recvmmsg<'a, I>( fd: RawFd, data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>, IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>, flags: MsgFlags, timeout: Option<crate::sys::time::TimeSpec> ) -> Result<Vec<RecvMsg<'a>>> where I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,1234 pub fn recvmmsg<'a, I>(
1235     fd: RawFd,
1236     data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
1237         IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
1238     flags: MsgFlags,
1239     timeout: Option<crate::sys::time::TimeSpec>
1240 ) -> Result<Vec<RecvMsg<'a>>>
1241     where
1242         I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
1243 {
1244     let iter = data.into_iter();
1245 
1246     let num_messages = iter.len();
1247 
1248     let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
1249 
1250     // Addresses should be pre-allocated.  pack_mhdr_to_receive will store them
1251     // as raw pointers, so we may not move them.  Turn the vec into a boxed
1252     // slice so we won't inadvertently reallocate the vec.
1253     let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages]
1254         .into_boxed_slice();
1255 
1256     let results: Vec<_> = iter.enumerate().map(|(i, d)| {
1257         let (msg_controllen, mhdr) = unsafe {
1258             pack_mhdr_to_receive(
1259                 d.iov.as_ref(),
1260                 &mut d.cmsg_buffer,
1261                 addresses[i].as_mut_ptr(),
1262             )
1263         };
1264 
1265         output.push(
1266             libc::mmsghdr {
1267                 msg_hdr: mhdr,
1268                 msg_len: 0,
1269             }
1270         );
1271 
1272         (msg_controllen as usize, &mut d.cmsg_buffer)
1273     }).collect();
1274 
1275     let timeout = if let Some(mut t) = timeout {
1276         t.as_mut() as *mut libc::timespec
1277     } else {
1278         ptr::null_mut()
1279     };
1280 
1281     let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
1282 
1283     let _ = Errno::result(ret)?;
1284 
1285     Ok(output
1286         .into_iter()
1287         .take(ret as usize)
1288         .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
1289         .zip(results.into_iter())
1290         .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
1291             unsafe {
1292                 read_mhdr(
1293                     mmsghdr.msg_hdr,
1294                     mmsghdr.msg_len as isize,
1295                     msg_controllen,
1296                     address,
1297                     cmsg_buffer
1298                 )
1299             }
1300         })
1301         .collect())
1302 }
1303 
read_mhdr<'a, 'b>( mhdr: msghdr, r: isize, msg_controllen: usize, address: sockaddr_storage, cmsg_buffer: &'a mut Option<&'b mut Vec<u8>> ) -> RecvMsg<'b>1304 unsafe fn read_mhdr<'a, 'b>(
1305     mhdr: msghdr,
1306     r: isize,
1307     msg_controllen: usize,
1308     address: sockaddr_storage,
1309     cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
1310 ) -> RecvMsg<'b> {
1311     let cmsghdr = {
1312         if mhdr.msg_controllen > 0 {
1313             // got control message(s)
1314             cmsg_buffer
1315                 .as_mut()
1316                 .unwrap()
1317                 .set_len(mhdr.msg_controllen as usize);
1318             debug_assert!(!mhdr.msg_control.is_null());
1319             debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
1320             CMSG_FIRSTHDR(&mhdr as *const msghdr)
1321         } else {
1322             ptr::null()
1323         }.as_ref()
1324     };
1325 
1326     let address = sockaddr_storage_to_addr(
1327         &address ,
1328          mhdr.msg_namelen as usize
1329     ).ok();
1330 
1331     RecvMsg {
1332         bytes: r as usize,
1333         cmsghdr,
1334         address,
1335         flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
1336         mhdr,
1337     }
1338 }
1339 
pack_mhdr_to_receive<'a, I>( iov: I, cmsg_buffer: &mut Option<&mut Vec<u8>>, address: *mut sockaddr_storage, ) -> (usize, msghdr) where I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,1340 unsafe fn pack_mhdr_to_receive<'a, I>(
1341     iov: I,
1342     cmsg_buffer: &mut Option<&mut Vec<u8>>,
1343     address: *mut sockaddr_storage,
1344 ) -> (usize, msghdr)
1345     where
1346         I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
1347 {
1348     let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
1349         .map(|v| (v.as_mut_ptr(), v.capacity()))
1350         .unwrap_or((ptr::null_mut(), 0));
1351 
1352     let mhdr = {
1353         // Musl's msghdr has private fields, so this is the only way to
1354         // initialize it.
1355         let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
1356         let p = mhdr.as_mut_ptr();
1357         (*p).msg_name = address as *mut c_void;
1358         (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
1359         (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
1360         (*p).msg_iovlen = iov.as_ref().len() as _;
1361         (*p).msg_control = msg_control as *mut c_void;
1362         (*p).msg_controllen = msg_controllen as _;
1363         (*p).msg_flags = 0;
1364         mhdr.assume_init()
1365     };
1366 
1367     (msg_controllen, mhdr)
1368 }
1369 
pack_mhdr_to_send<'a, I, C>( cmsg_buffer: &mut [u8], iov: I, cmsgs: C, addr: Option<&SockAddr> ) -> msghdr where I: AsRef<[IoVec<&'a [u8]>]>, C: AsRef<[ControlMessage<'a>]>1370 fn pack_mhdr_to_send<'a, I, C>(
1371     cmsg_buffer: &mut [u8],
1372     iov: I,
1373     cmsgs: C,
1374     addr: Option<&SockAddr>
1375 ) -> msghdr
1376     where
1377         I: AsRef<[IoVec<&'a [u8]>]>,
1378         C: AsRef<[ControlMessage<'a>]>
1379 {
1380     let capacity = cmsg_buffer.len();
1381 
1382     // Next encode the sending address, if provided
1383     let (name, namelen) = match addr {
1384         Some(addr) => {
1385             let (x, y) = addr.as_ffi_pair();
1386             (x as *const _, y)
1387         },
1388         None => (ptr::null(), 0),
1389     };
1390 
1391     // The message header must be initialized before the individual cmsgs.
1392     let cmsg_ptr = if capacity > 0 {
1393         cmsg_buffer.as_ptr() as *mut c_void
1394     } else {
1395         ptr::null_mut()
1396     };
1397 
1398     let mhdr = unsafe {
1399         // Musl's msghdr has private fields, so this is the only way to
1400         // initialize it.
1401         let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
1402         let p = mhdr.as_mut_ptr();
1403         (*p).msg_name = name as *mut _;
1404         (*p).msg_namelen = namelen;
1405         // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
1406         // the buffer, but the standard says that it takes a mutable pointer
1407         (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
1408         (*p).msg_iovlen = iov.as_ref().len() as _;
1409         (*p).msg_control = cmsg_ptr;
1410         (*p).msg_controllen = capacity as _;
1411         (*p).msg_flags = 0;
1412         mhdr.assume_init()
1413     };
1414 
1415     // Encode each cmsg.  This must happen after initializing the header because
1416     // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
1417     // CMSG_FIRSTHDR is always safe
1418     let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
1419     for cmsg in cmsgs.as_ref() {
1420         assert_ne!(pmhdr, ptr::null_mut());
1421         // Safe because we know that pmhdr is valid, and we initialized it with
1422         // sufficient space
1423         unsafe { cmsg.encode_into(pmhdr) };
1424         // Safe because mhdr is valid
1425         pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
1426     }
1427 
1428     mhdr
1429 }
1430 
1431 /// Receive message in scatter-gather vectors from a socket, and
1432 /// optionally receive ancillary data into the provided buffer.
1433 /// If no ancillary data is desired, use () as the type parameter.
1434 ///
1435 /// # Arguments
1436 ///
1437 /// * `fd`:             Socket file descriptor
1438 /// * `iov`:            Scatter-gather list of buffers to receive the message
1439 /// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
1440 ///                     [`cmsg_space!`](macro.cmsg_space.html)
1441 /// * `flags`:          Optional flags passed directly to the operating system.
1442 ///
1443 /// # References
1444 /// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], mut cmsg_buffer: Option<&'a mut Vec<u8>>, flags: MsgFlags) -> Result<RecvMsg<'a>>1445 pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
1446                    mut cmsg_buffer: Option<&'a mut Vec<u8>>,
1447                    flags: MsgFlags) -> Result<RecvMsg<'a>>
1448 {
1449     let mut address = mem::MaybeUninit::uninit();
1450 
1451     let (msg_controllen, mut mhdr) = unsafe {
1452         pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr())
1453     };
1454 
1455     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
1456 
1457     let r = Errno::result(ret)?;
1458 
1459     Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) })
1460 }
1461 
1462 
1463 /// Create an endpoint for communication
1464 ///
1465 /// The `protocol` specifies a particular protocol to be used with the
1466 /// socket.  Normally only a single protocol exists to support a
1467 /// particular socket type within a given protocol family, in which case
1468 /// protocol can be specified as `None`.  However, it is possible that many
1469 /// protocols may exist, in which case a particular protocol must be
1470 /// specified in this manner.
1471 ///
1472 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd>1473 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
1474     let protocol = match protocol.into() {
1475         None => 0,
1476         Some(p) => p as c_int,
1477     };
1478 
1479     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
1480     // little easier to understand by separating it out. So we have to merge these bitfields
1481     // here.
1482     let mut ty = ty as c_int;
1483     ty |= flags.bits();
1484 
1485     let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
1486 
1487     Errno::result(res)
1488 }
1489 
1490 /// Create a pair of connected sockets
1491 ///
1492 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T, flags: SockFlag) -> Result<(RawFd, RawFd)>1493 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
1494                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
1495     let protocol = match protocol.into() {
1496         None => 0,
1497         Some(p) => p as c_int,
1498     };
1499 
1500     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
1501     // little easier to understand by separating it out. So we have to merge these bitfields
1502     // here.
1503     let mut ty = ty as c_int;
1504     ty |= flags.bits();
1505 
1506     let mut fds = [-1, -1];
1507 
1508     let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
1509     Errno::result(res)?;
1510 
1511     Ok((fds[0], fds[1]))
1512 }
1513 
1514 /// Listen for connections on a socket
1515 ///
1516 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
listen(sockfd: RawFd, backlog: usize) -> Result<()>1517 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
1518     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
1519 
1520     Errno::result(res).map(drop)
1521 }
1522 
1523 /// Bind a name to a socket
1524 ///
1525 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
bind(fd: RawFd, addr: &SockAddr) -> Result<()>1526 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
1527     let res = unsafe {
1528         let (ptr, len) = addr.as_ffi_pair();
1529         libc::bind(fd, ptr, len)
1530     };
1531 
1532     Errno::result(res).map(drop)
1533 }
1534 
1535 /// Accept a connection on a socket
1536 ///
1537 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
accept(sockfd: RawFd) -> Result<RawFd>1538 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
1539     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
1540 
1541     Errno::result(res)
1542 }
1543 
1544 /// Accept a connection on a socket
1545 ///
1546 /// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
1547 #[cfg(any(all(
1548             target_os = "android",
1549             any(
1550                 target_arch = "aarch64",
1551                 target_arch = "x86",
1552                 target_arch = "x86_64"
1553             )
1554           ),
1555           target_os = "freebsd",
1556           target_os = "linux",
1557           target_os = "openbsd"))]
accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd>1558 pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
1559     let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
1560 
1561     Errno::result(res)
1562 }
1563 
1564 /// Initiate a connection on a socket
1565 ///
1566 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
connect(fd: RawFd, addr: &SockAddr) -> Result<()>1567 pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
1568     let res = unsafe {
1569         let (ptr, len) = addr.as_ffi_pair();
1570         libc::connect(fd, ptr, len)
1571     };
1572 
1573     Errno::result(res).map(drop)
1574 }
1575 
1576 /// Receive data from a connection-oriented socket. Returns the number of
1577 /// bytes read
1578 ///
1579 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize>1580 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
1581     unsafe {
1582         let ret = libc::recv(
1583             sockfd,
1584             buf.as_ptr() as *mut c_void,
1585             buf.len() as size_t,
1586             flags.bits());
1587 
1588         Errno::result(ret).map(|r| r as usize)
1589     }
1590 }
1591 
1592 /// Receive data from a connectionless or connection-oriented socket. Returns
1593 /// the number of bytes read and, for connectionless sockets,  the socket
1594 /// address of the sender.
1595 ///
1596 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, Option<SockAddr>)>1597 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
1598     -> Result<(usize, Option<SockAddr>)>
1599 {
1600     unsafe {
1601         let mut addr: sockaddr_storage = mem::zeroed();
1602         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1603 
1604         let ret = Errno::result(libc::recvfrom(
1605             sockfd,
1606             buf.as_ptr() as *mut c_void,
1607             buf.len() as size_t,
1608             0,
1609             &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
1610             &mut len as *mut socklen_t))? as usize;
1611 
1612         match sockaddr_storage_to_addr(&addr, len as usize) {
1613             Err(Errno::ENOTCONN) => Ok((ret, None)),
1614             Ok(addr) => Ok((ret, Some(addr))),
1615             Err(e) => Err(e)
1616         }
1617     }
1618 }
1619 
1620 /// Send a message to a socket
1621 ///
1622 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize>1623 pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
1624     let ret = unsafe {
1625         let (ptr, len) = addr.as_ffi_pair();
1626         libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
1627     };
1628 
1629     Errno::result(ret).map(|r| r as usize)
1630 }
1631 
1632 /// Send data to a connection-oriented socket. Returns the number of bytes read
1633 ///
1634 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize>1635 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
1636     let ret = unsafe {
1637         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
1638     };
1639 
1640     Errno::result(ret).map(|r| r as usize)
1641 }
1642 
1643 /*
1644  *
1645  * ===== Socket Options =====
1646  *
1647  */
1648 
1649 /// Represents a socket option that can be accessed or set. Used as an argument
1650 /// to `getsockopt`
1651 pub trait GetSockOpt : Copy {
1652     type Val;
1653 
1654     #[doc(hidden)]
get(&self, fd: RawFd) -> Result<Self::Val>1655     fn get(&self, fd: RawFd) -> Result<Self::Val>;
1656 }
1657 
1658 /// Represents a socket option that can be accessed or set. Used as an argument
1659 /// to `setsockopt`
1660 pub trait SetSockOpt : Clone {
1661     type Val;
1662 
1663     #[doc(hidden)]
set(&self, fd: RawFd, val: &Self::Val) -> Result<()>1664     fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
1665 }
1666 
1667 /// Get the current value for the requested socket option
1668 ///
1669 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val>1670 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
1671     opt.get(fd)
1672 }
1673 
1674 /// Sets the value for the requested socket option
1675 ///
1676 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
1677 ///
1678 /// # Examples
1679 ///
1680 /// ```
1681 /// use nix::sys::socket::setsockopt;
1682 /// use nix::sys::socket::sockopt::KeepAlive;
1683 /// use std::net::TcpListener;
1684 /// use std::os::unix::io::AsRawFd;
1685 ///
1686 /// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
1687 /// let fd = listener.as_raw_fd();
1688 /// let res = setsockopt(fd, KeepAlive, &true);
1689 /// assert!(res.is_ok());
1690 /// ```
setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>1691 pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
1692     opt.set(fd, val)
1693 }
1694 
1695 /// Get the address of the peer connected to the socket `fd`.
1696 ///
1697 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
getpeername(fd: RawFd) -> Result<SockAddr>1698 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
1699     unsafe {
1700         let mut addr = mem::MaybeUninit::uninit();
1701         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1702 
1703         let ret = libc::getpeername(
1704             fd,
1705             addr.as_mut_ptr() as *mut libc::sockaddr,
1706             &mut len
1707         );
1708 
1709         Errno::result(ret)?;
1710 
1711         sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
1712     }
1713 }
1714 
1715 /// Get the current address to which the socket `fd` is bound.
1716 ///
1717 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
getsockname(fd: RawFd) -> Result<SockAddr>1718 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
1719     unsafe {
1720         let mut addr = mem::MaybeUninit::uninit();
1721         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1722 
1723         let ret = libc::getsockname(
1724             fd,
1725             addr.as_mut_ptr() as *mut libc::sockaddr,
1726             &mut len
1727         );
1728 
1729         Errno::result(ret)?;
1730 
1731         sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
1732     }
1733 }
1734 
1735 /// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
1736 /// certain size.
1737 ///
1738 /// In C this would usually be done by casting.  The `len` argument
1739 /// should be the number of bytes in the `sockaddr_storage` that are actually
1740 /// allocated and valid.  It must be at least as large as all the useful parts
1741 /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
1742 /// include the terminating null.
sockaddr_storage_to_addr( addr: &sockaddr_storage, len: usize) -> Result<SockAddr>1743 pub fn sockaddr_storage_to_addr(
1744     addr: &sockaddr_storage,
1745     len: usize) -> Result<SockAddr> {
1746 
1747     assert!(len <= mem::size_of::<sockaddr_un>());
1748     if len < mem::size_of_val(&addr.ss_family) {
1749         return Err(Error::from(Errno::ENOTCONN));
1750     }
1751 
1752     match c_int::from(addr.ss_family) {
1753         libc::AF_INET => {
1754             assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
1755             let sin = unsafe {
1756                 *(addr as *const sockaddr_storage as *const sockaddr_in)
1757             };
1758             Ok(SockAddr::Inet(InetAddr::V4(sin)))
1759         }
1760         libc::AF_INET6 => {
1761             assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
1762             let sin6 = unsafe {
1763                 *(addr as *const _ as *const sockaddr_in6)
1764             };
1765             Ok(SockAddr::Inet(InetAddr::V6(sin6)))
1766         }
1767         libc::AF_UNIX => {
1768             let pathlen = len - offset_of!(sockaddr_un, sun_path);
1769             let sun = unsafe {
1770                 *(addr as *const _ as *const sockaddr_un)
1771             };
1772             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
1773         }
1774         #[cfg(any(target_os = "android", target_os = "linux"))]
1775         libc::AF_PACKET => {
1776             use libc::sockaddr_ll;
1777             // Apparently the Linux kernel can return smaller sizes when
1778             // the value in the last element of sockaddr_ll (`sll_addr`) is
1779             // smaller than the declared size of that field
1780             assert!(len as usize <= mem::size_of::<sockaddr_ll>());
1781             let sll = unsafe {
1782                 *(addr as *const _ as *const sockaddr_ll)
1783             };
1784             Ok(SockAddr::Link(LinkAddr(sll)))
1785         }
1786         #[cfg(any(target_os = "android", target_os = "linux"))]
1787         libc::AF_NETLINK => {
1788             use libc::sockaddr_nl;
1789             let snl = unsafe {
1790                 *(addr as *const _ as *const sockaddr_nl)
1791             };
1792             Ok(SockAddr::Netlink(NetlinkAddr(snl)))
1793         }
1794         #[cfg(any(target_os = "android", target_os = "linux"))]
1795         libc::AF_ALG => {
1796             use libc::sockaddr_alg;
1797             let salg = unsafe {
1798                 *(addr as *const _ as *const sockaddr_alg)
1799             };
1800             Ok(SockAddr::Alg(AlgAddr(salg)))
1801         }
1802         #[cfg(any(target_os = "android", target_os = "linux"))]
1803         libc::AF_VSOCK => {
1804             use libc::sockaddr_vm;
1805             let svm = unsafe {
1806                 *(addr as *const _ as *const sockaddr_vm)
1807             };
1808             Ok(SockAddr::Vsock(VsockAddr(svm)))
1809         }
1810         af => panic!("unexpected address family {}", af),
1811     }
1812 }
1813 
1814 
1815 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1816 pub enum Shutdown {
1817     /// Further receptions will be disallowed.
1818     Read,
1819     /// Further  transmissions will be disallowed.
1820     Write,
1821     /// Further receptions and transmissions will be disallowed.
1822     Both,
1823 }
1824 
1825 /// Shut down part of a full-duplex connection.
1826 ///
1827 /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
shutdown(df: RawFd, how: Shutdown) -> Result<()>1828 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
1829     unsafe {
1830         use libc::shutdown;
1831 
1832         let how = match how {
1833             Shutdown::Read  => libc::SHUT_RD,
1834             Shutdown::Write => libc::SHUT_WR,
1835             Shutdown::Both  => libc::SHUT_RDWR,
1836         };
1837 
1838         Errno::result(shutdown(df, how)).map(drop)
1839     }
1840 }
1841 
1842 #[cfg(test)]
1843 mod tests {
1844     #[test]
can_use_cmsg_space()1845     fn can_use_cmsg_space() {
1846         let _ = cmsg_space!(u8);
1847     }
1848 }
1849