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