1 //! Socket interface functions
2 //!
3 //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
4 use {Error, Result};
5 use 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 sys::time::TimeVal;
11 use 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 ::sys::socket::addr::netlink::NetlinkAddr;
34 #[cfg(any(target_os = "android", target_os = "linux"))]
35 pub use sys::socket::addr::alg::AlgAddr;
36 #[cfg(target_os = "linux")]
37 pub use 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 for UNIX sockets.
193         #[repr(transparent)]
194         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
195         pub struct UnixCredentials(libc::ucred);
196 
197         impl UnixCredentials {
198             /// Returns the process identifier
199             pub fn pid(&self) -> libc::pid_t {
200                 self.0.pid
201             }
202 
203             /// Returns the user identifier
204             pub fn uid(&self) -> libc::uid_t {
205                 self.0.uid
206             }
207 
208             /// Returns the group identifier
209             pub fn gid(&self) -> libc::gid_t {
210                 self.0.gid
211             }
212         }
213 
214         impl From<libc::ucred> for UnixCredentials {
215             fn from(cred: libc::ucred) -> Self {
216                 UnixCredentials(cred)
217             }
218         }
219 
220         impl Into<libc::ucred> for UnixCredentials {
221             fn into(self) -> libc::ucred {
222                 self.0
223             }
224         }
225     }
226 }
227 
228 /// Request for multicast socket operations
229 ///
230 /// This is a wrapper type around `ip_mreq`.
231 #[repr(C)]
232 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
233 pub struct IpMembershipRequest(libc::ip_mreq);
234 
235 impl IpMembershipRequest {
236     /// Instantiate a new `IpMembershipRequest`
237     ///
238     /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self239     pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
240         IpMembershipRequest(libc::ip_mreq {
241             imr_multiaddr: group.0,
242             imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
243         })
244     }
245 }
246 
247 /// Request for ipv6 multicast socket operations
248 ///
249 /// This is a wrapper type around `ipv6_mreq`.
250 #[repr(C)]
251 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
252 pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
253 
254 impl Ipv6MembershipRequest {
255     /// Instantiate a new `Ipv6MembershipRequest`
new(group: Ipv6Addr) -> Self256     pub fn new(group: Ipv6Addr) -> Self {
257         Ipv6MembershipRequest(libc::ipv6_mreq {
258             ipv6mr_multiaddr: group.0,
259             ipv6mr_interface: 0,
260         })
261     }
262 }
263 
264 /// Create a buffer large enough for storing some control messages as returned
265 /// by [`recvmsg`](fn.recvmsg.html).
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// # #[macro_use] extern crate nix;
271 /// # use nix::sys::time::TimeVal;
272 /// # use std::os::unix::io::RawFd;
273 /// # fn main() {
274 /// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
275 /// let _ = cmsg_space!(TimeVal);
276 /// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
277 /// // with two file descriptors
278 /// let _ = cmsg_space!([RawFd; 2]);
279 /// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
280 /// // and a `ControlMessageOwned::ScmTimestamp` message
281 /// let _ = cmsg_space!(RawFd, TimeVal);
282 /// # }
283 /// ```
284 // Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
285 // stack-allocated array.
286 #[macro_export]
287 macro_rules! cmsg_space {
288     ( $( $x:ty ),* ) => {
289         {
290             use nix::sys::socket::{c_uint, CMSG_SPACE};
291             use std::mem;
292             let mut space = 0;
293             $(
294                 // CMSG_SPACE is always safe
295                 space += unsafe {
296                     CMSG_SPACE(mem::size_of::<$x>() as c_uint)
297                 } as usize;
298             )*
299             Vec::<u8>::with_capacity(space)
300         }
301     }
302 }
303 
304 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
305 pub struct RecvMsg<'a> {
306     pub bytes: usize,
307     cmsghdr: Option<&'a cmsghdr>,
308     pub address: Option<SockAddr>,
309     pub flags: MsgFlags,
310     mhdr: msghdr,
311 }
312 
313 impl<'a> RecvMsg<'a> {
314     /// Iterate over the valid control messages pointed to by this
315     /// msghdr.
cmsgs(&self) -> CmsgIterator316     pub fn cmsgs(&self) -> CmsgIterator {
317         CmsgIterator {
318             cmsghdr: self.cmsghdr,
319             mhdr: &self.mhdr
320         }
321     }
322 }
323 
324 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
325 pub struct CmsgIterator<'a> {
326     /// Control message buffer to decode from. Must adhere to cmsg alignment.
327     cmsghdr: Option<&'a cmsghdr>,
328     mhdr: &'a msghdr
329 }
330 
331 impl<'a> Iterator for CmsgIterator<'a> {
332     type Item = ControlMessageOwned;
333 
next(&mut self) -> Option<ControlMessageOwned>334     fn next(&mut self) -> Option<ControlMessageOwned> {
335         match self.cmsghdr {
336             None => None,   // No more messages
337             Some(hdr) => {
338                 // Get the data.
339                 // Safe if cmsghdr points to valid data returned by recvmsg(2)
340                 let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
341                 // Advance the internal pointer.  Safe if mhdr and cmsghdr point
342                 // to valid data returned by recvmsg(2)
343                 self.cmsghdr = unsafe {
344                     let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
345                     p.as_ref()
346                 };
347                 cm
348             }
349         }
350     }
351 }
352 
353 /// A type-safe wrapper around a single control message, as used with
354 /// [`recvmsg`](#fn.recvmsg).
355 ///
356 /// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
357 //  Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
358 //  sendmsg.  However, on some platforms the messages returned by recvmsg may be
359 //  unaligned.  ControlMessageOwned takes those messages by copy, obviating any
360 //  alignment issues.
361 //
362 //  See https://github.com/nix-rust/nix/issues/999
363 #[derive(Clone, Debug, Eq, PartialEq)]
364 pub enum ControlMessageOwned {
365     /// Received version of
366     /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
367     ScmRights(Vec<RawFd>),
368     /// Received version of
369     /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
370     #[cfg(any(target_os = "android", target_os = "linux"))]
371     ScmCredentials(UnixCredentials),
372     /// A message of type `SCM_TIMESTAMP`, containing the time the
373     /// packet was received by the kernel.
374     ///
375     /// See the kernel's explanation in "SO_TIMESTAMP" of
376     /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
377     ///
378     /// # Examples
379     ///
380     // Disable this test on FreeBSD i386
381     // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
382     #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
383     #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
384     /// # #[macro_use] extern crate nix;
385     /// # use nix::sys::socket::*;
386     /// # use nix::sys::uio::IoVec;
387     /// # use nix::sys::time::*;
388     /// # use std::time::*;
389     /// # fn main() {
390     /// // Set up
391     /// let message = "Ohayō!".as_bytes();
392     /// let in_socket = socket(
393     ///     AddressFamily::Inet,
394     ///     SockType::Datagram,
395     ///     SockFlag::empty(),
396     ///     None).unwrap();
397     /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
398     /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
399     /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
400     /// let address = getsockname(in_socket).unwrap();
401     /// // Get initial time
402     /// let time0 = SystemTime::now();
403     /// // Send the message
404     /// let iov = [IoVec::from_slice(message)];
405     /// let flags = MsgFlags::empty();
406     /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
407     /// assert_eq!(message.len(), l);
408     /// // Receive the message
409     /// let mut buffer = vec![0u8; message.len()];
410     /// let mut cmsgspace = cmsg_space!(TimeVal);
411     /// let iov = [IoVec::from_mut_slice(&mut buffer)];
412     /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
413     /// let rtime = match r.cmsgs().next() {
414     ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
415     ///     Some(_) => panic!("Unexpected control message"),
416     ///     None => panic!("No control message")
417     /// };
418     /// // Check the final time
419     /// let time1 = SystemTime::now();
420     /// // the packet's received timestamp should lie in-between the two system
421     /// // times, unless the system clock was adjusted in the meantime.
422     /// let rduration = Duration::new(rtime.tv_sec() as u64,
423     ///                               rtime.tv_usec() as u32 * 1000);
424     /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
425     /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
426     /// // Close socket
427     /// nix::unistd::close(in_socket).unwrap();
428     /// # }
429     /// ```
430     ScmTimestamp(TimeVal),
431     #[cfg(any(
432         target_os = "android",
433         target_os = "ios",
434         target_os = "linux",
435         target_os = "macos",
436         target_os = "netbsd",
437     ))]
438     Ipv4PacketInfo(libc::in_pktinfo),
439     #[cfg(any(
440         target_os = "android",
441         target_os = "dragonfly",
442         target_os = "freebsd",
443         target_os = "ios",
444         target_os = "linux",
445         target_os = "macos",
446         target_os = "openbsd",
447         target_os = "netbsd",
448     ))]
449     Ipv6PacketInfo(libc::in6_pktinfo),
450     #[cfg(any(
451         target_os = "freebsd",
452         target_os = "ios",
453         target_os = "macos",
454         target_os = "netbsd",
455         target_os = "openbsd",
456     ))]
457     Ipv4RecvIf(libc::sockaddr_dl),
458     #[cfg(any(
459         target_os = "freebsd",
460         target_os = "ios",
461         target_os = "macos",
462         target_os = "netbsd",
463         target_os = "openbsd",
464     ))]
465     Ipv4RecvDstAddr(libc::in_addr),
466     /// Catch-all variant for unimplemented cmsg types.
467     #[doc(hidden)]
468     Unknown(UnknownCmsg),
469 }
470 
471 impl ControlMessageOwned {
472     /// Decodes a `ControlMessageOwned` from raw bytes.
473     ///
474     /// This is only safe to call if the data is correct for the message type
475     /// specified in the header. Normally, the kernel ensures that this is the
476     /// case. "Correct" in this case includes correct length, alignment and
477     /// actual content.
478     // Clippy complains about the pointer alignment of `p`, not understanding
479     // that it's being fed to a function that can handle that.
480     #[allow(clippy::cast_ptr_alignment)]
decode_from(header: &cmsghdr) -> ControlMessageOwned481     unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
482     {
483         let p = CMSG_DATA(header);
484         let len = header as *const _ as usize + header.cmsg_len as usize
485             - p as usize;
486         match (header.cmsg_level, header.cmsg_type) {
487             (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
488                 let n = len / mem::size_of::<RawFd>();
489                 let mut fds = Vec::with_capacity(n);
490                 for i in 0..n {
491                     let fdp = (p as *const RawFd).add(i);
492                     fds.push(ptr::read_unaligned(fdp));
493                 }
494                 ControlMessageOwned::ScmRights(fds)
495             },
496             #[cfg(any(target_os = "android", target_os = "linux"))]
497             (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
498                 let cred: libc::ucred = ptr::read_unaligned(p as *const _);
499                 ControlMessageOwned::ScmCredentials(cred.into())
500             }
501             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
502                 let tv: libc::timeval = ptr::read_unaligned(p as *const _);
503                 ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
504             },
505             #[cfg(any(
506                 target_os = "android",
507                 target_os = "freebsd",
508                 target_os = "ios",
509                 target_os = "linux",
510                 target_os = "macos"
511             ))]
512             (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
513                 let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
514                 ControlMessageOwned::Ipv6PacketInfo(info)
515             }
516             #[cfg(any(
517                 target_os = "android",
518                 target_os = "ios",
519                 target_os = "linux",
520                 target_os = "macos",
521                 target_os = "netbsd",
522             ))]
523             (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
524                 let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
525                 ControlMessageOwned::Ipv4PacketInfo(info)
526             }
527             #[cfg(any(
528                 target_os = "freebsd",
529                 target_os = "ios",
530                 target_os = "macos",
531                 target_os = "netbsd",
532                 target_os = "openbsd",
533             ))]
534             (libc::IPPROTO_IP, libc::IP_RECVIF) => {
535                 let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
536                 ControlMessageOwned::Ipv4RecvIf(dl)
537             },
538             #[cfg(any(
539                 target_os = "freebsd",
540                 target_os = "ios",
541                 target_os = "macos",
542                 target_os = "netbsd",
543                 target_os = "openbsd",
544             ))]
545             (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
546                 let dl = ptr::read_unaligned(p as *const libc::in_addr);
547                 ControlMessageOwned::Ipv4RecvDstAddr(dl)
548             },
549             (_, _) => {
550                 let sl = slice::from_raw_parts(p, len);
551                 let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
552                 ControlMessageOwned::Unknown(ucmsg)
553             }
554         }
555     }
556 }
557 
558 /// A type-safe zero-copy wrapper around a single control message, as used wih
559 /// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
560 /// exhaustively pattern-match it.
561 ///
562 /// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
563 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
564 pub enum ControlMessage<'a> {
565     /// A message of type `SCM_RIGHTS`, containing an array of file
566     /// descriptors passed between processes.
567     ///
568     /// See the description in the "Ancillary messages" section of the
569     /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
570     ///
571     /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
572     /// recommended since it causes platform-dependent behaviour: It might
573     /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
574     /// Instead, you can put all fds to be passed into a single `ScmRights`
575     /// message.
576     ScmRights(&'a [RawFd]),
577     /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
578     /// a process connected to the socket.
579     ///
580     /// This is similar to the socket option `SO_PEERCRED`, but requires a
581     /// process to explicitly send its credentials. A process running as root is
582     /// allowed to specify any credentials, while credentials sent by other
583     /// processes are verified by the kernel.
584     ///
585     /// For further information, please refer to the
586     /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
587     #[cfg(any(target_os = "android", target_os = "linux"))]
588     ScmCredentials(&'a UnixCredentials),
589 
590     /// Set IV for `AF_ALG` crypto API.
591     ///
592     /// For further information, please refer to the
593     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
594     #[cfg(any(
595         target_os = "android",
596         target_os = "linux",
597     ))]
598     AlgSetIv(&'a [u8]),
599     /// Set crypto operation for `AF_ALG` crypto API. It may be one of
600     /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
601     ///
602     /// For further information, please refer to the
603     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
604     #[cfg(any(
605         target_os = "android",
606         target_os = "linux",
607     ))]
608     AlgSetOp(&'a libc::c_int),
609     /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
610     /// for `AF_ALG` crypto API.
611     ///
612     /// For further information, please refer to the
613     /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
614     #[cfg(any(
615         target_os = "android",
616         target_os = "linux",
617     ))]
618     AlgSetAeadAssoclen(&'a u32),
619 
620 }
621 
622 // An opaque structure used to prevent cmsghdr from being a public type
623 #[doc(hidden)]
624 #[derive(Clone, Debug, Eq, PartialEq)]
625 pub struct UnknownCmsg(cmsghdr, Vec<u8>);
626 
627 impl<'a> ControlMessage<'a> {
628     /// The value of CMSG_SPACE on this message.
629     /// Safe because CMSG_SPACE is always safe
space(&self) -> usize630     fn space(&self) -> usize {
631         unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
632     }
633 
634     /// The value of CMSG_LEN on this message.
635     /// Safe because CMSG_LEN is always safe
636     #[cfg(any(target_os = "android",
637               all(target_os = "linux", not(target_env = "musl"))))]
cmsg_len(&self) -> usize638     fn cmsg_len(&self) -> usize {
639         unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
640     }
641 
642     #[cfg(not(any(target_os = "android",
643                   all(target_os = "linux", not(target_env = "musl")))))]
cmsg_len(&self) -> libc::c_uint644     fn cmsg_len(&self) -> libc::c_uint {
645         unsafe{CMSG_LEN(self.len() as libc::c_uint)}
646     }
647 
648     /// Return a reference to the payload data as a byte pointer
copy_to_cmsg_data(&self, cmsg_data: *mut u8)649     fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
650         let data_ptr = match *self {
651             ControlMessage::ScmRights(fds) => {
652                 fds as *const _ as *const u8
653             },
654             #[cfg(any(target_os = "android", target_os = "linux"))]
655             ControlMessage::ScmCredentials(creds) => {
656                 &creds.0 as *const libc::ucred as *const u8
657             }
658             #[cfg(any(target_os = "android", target_os = "linux"))]
659             ControlMessage::AlgSetIv(iv) => {
660                 unsafe {
661                     let alg_iv = cmsg_data as *mut libc::af_alg_iv;
662                     (*alg_iv).ivlen = iv.len() as u32;
663                     ptr::copy_nonoverlapping(
664                         iv.as_ptr(),
665                         (*alg_iv).iv.as_mut_ptr(),
666                         iv.len()
667                     );
668                 };
669                 return
670             },
671             #[cfg(any(target_os = "android", target_os = "linux"))]
672             ControlMessage::AlgSetOp(op) => {
673                 op as *const _ as *const u8
674             },
675             #[cfg(any(target_os = "android", target_os = "linux"))]
676             ControlMessage::AlgSetAeadAssoclen(len) => {
677                 len as *const _ as *const u8
678             },
679         };
680         unsafe {
681             ptr::copy_nonoverlapping(
682                 data_ptr,
683                 cmsg_data,
684                 self.len()
685             )
686         };
687     }
688 
689     /// The size of the payload, excluding its cmsghdr
len(&self) -> usize690     fn len(&self) -> usize {
691         match *self {
692             ControlMessage::ScmRights(fds) => {
693                 mem::size_of_val(fds)
694             },
695             #[cfg(any(target_os = "android", target_os = "linux"))]
696             ControlMessage::ScmCredentials(creds) => {
697                 mem::size_of_val(creds)
698             }
699             #[cfg(any(target_os = "android", target_os = "linux"))]
700             ControlMessage::AlgSetIv(iv) => {
701                 mem::size_of::<libc::af_alg_iv>() + iv.len()
702             },
703             #[cfg(any(target_os = "android", target_os = "linux"))]
704             ControlMessage::AlgSetOp(op) => {
705                 mem::size_of_val(op)
706             },
707             #[cfg(any(target_os = "android", target_os = "linux"))]
708             ControlMessage::AlgSetAeadAssoclen(len) => {
709                 mem::size_of_val(len)
710             },
711         }
712     }
713 
714     /// Returns the value to put into the `cmsg_level` field of the header.
cmsg_level(&self) -> libc::c_int715     fn cmsg_level(&self) -> libc::c_int {
716         match *self {
717             ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
718             #[cfg(any(target_os = "android", target_os = "linux"))]
719             ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
720             #[cfg(any(target_os = "android", target_os = "linux"))]
721             ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
722                 ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG ,
723         }
724     }
725 
726     /// Returns the value to put into the `cmsg_type` field of the header.
cmsg_type(&self) -> libc::c_int727     fn cmsg_type(&self) -> libc::c_int {
728         match *self {
729             ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
730             #[cfg(any(target_os = "android", target_os = "linux"))]
731             ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
732             #[cfg(any(target_os = "android", target_os = "linux"))]
733             ControlMessage::AlgSetIv(_) => {
734                 libc::ALG_SET_IV
735             },
736             #[cfg(any(target_os = "android", target_os = "linux"))]
737             ControlMessage::AlgSetOp(_) => {
738                 libc::ALG_SET_OP
739             },
740             #[cfg(any(target_os = "android", target_os = "linux"))]
741             ControlMessage::AlgSetAeadAssoclen(_) => {
742                 libc::ALG_SET_AEAD_ASSOCLEN
743             },
744         }
745     }
746 
747     // Unsafe: cmsg must point to a valid cmsghdr with enough space to
748     // encode self.
encode_into(&self, cmsg: *mut cmsghdr)749     unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
750         (*cmsg).cmsg_level = self.cmsg_level();
751         (*cmsg).cmsg_type = self.cmsg_type();
752         (*cmsg).cmsg_len = self.cmsg_len();
753         self.copy_to_cmsg_data(CMSG_DATA(cmsg));
754     }
755 }
756 
757 
758 /// Send data in scatter-gather vectors to a socket, possibly accompanied
759 /// by ancillary data. Optionally direct the message at the given address,
760 /// as with sendto.
761 ///
762 /// Allocates if cmsgs is nonempty.
sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>763 pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
764                flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
765 {
766     let capacity = cmsgs.iter().map(|c| c.space()).sum();
767 
768     // First size the buffer needed to hold the cmsgs.  It must be zeroed,
769     // because subsequent code will not clear the padding bytes.
770     let cmsg_buffer = vec![0u8; capacity];
771 
772     // Next encode the sending address, if provided
773     let (name, namelen) = match addr {
774         Some(addr) => {
775             let (x, y) = unsafe { addr.as_ffi_pair() };
776             (x as *const _, y)
777         },
778         None => (ptr::null(), 0),
779     };
780 
781     // The message header must be initialized before the individual cmsgs.
782     let cmsg_ptr = if capacity > 0 {
783         cmsg_buffer.as_ptr() as *mut c_void
784     } else {
785         ptr::null_mut()
786     };
787 
788     let mhdr = unsafe {
789         // Musl's msghdr has private fields, so this is the only way to
790         // initialize it.
791         let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
792         let p = mhdr.as_mut_ptr();
793         (*p).msg_name = name as *mut _;
794         (*p).msg_namelen = namelen;
795         // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
796         // the buffer, but the standard says that it takes a mutable pointer
797         (*p).msg_iov = iov.as_ptr() as *mut _;
798         (*p).msg_iovlen = iov.len() as _;
799         (*p).msg_control = cmsg_ptr;
800         (*p).msg_controllen = capacity as _;
801         (*p).msg_flags = 0;
802         mhdr.assume_init()
803     };
804 
805     // Encode each cmsg.  This must happen after initializing the header because
806     // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
807     // CMSG_FIRSTHDR is always safe
808     let mut pmhdr: *mut cmsghdr = unsafe{CMSG_FIRSTHDR(&mhdr as *const msghdr)};
809     for cmsg in cmsgs {
810         assert_ne!(pmhdr, ptr::null_mut());
811         // Safe because we know that pmhdr is valid, and we initialized it with
812         // sufficient space
813         unsafe { cmsg.encode_into(pmhdr) };
814         // Safe because mhdr is valid
815         pmhdr = unsafe{CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr)};
816     }
817 
818     let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
819 
820     Errno::result(ret).map(|r| r as usize)
821 }
822 
823 /// Receive message in scatter-gather vectors from a socket, and
824 /// optionally receive ancillary data into the provided buffer.
825 /// If no ancillary data is desired, use () as the type parameter.
826 ///
827 /// # Arguments
828 ///
829 /// * `fd`:             Socket file descriptor
830 /// * `iov`:            Scatter-gather list of buffers to receive the message
831 /// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
832 ///                     [`cmsg_space!`](macro.cmsg_space.html)
833 /// * `flags`:          Optional flags passed directly to the operating system.
834 ///
835 /// # References
836 /// [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>>837 pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
838                    mut cmsg_buffer: Option<&'a mut Vec<u8>>,
839                    flags: MsgFlags) -> Result<RecvMsg<'a>>
840 {
841     let mut address = mem::MaybeUninit::uninit();
842     let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
843         .map(|v| (v.as_mut_ptr(), v.capacity()))
844         .unwrap_or((ptr::null_mut(), 0));
845     let mut mhdr = {
846         unsafe {
847             // Musl's msghdr has private fields, so this is the only way to
848             // initialize it.
849             let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
850             let p = mhdr.as_mut_ptr();
851             (*p).msg_name = address.as_mut_ptr() as *mut c_void;
852             (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
853             (*p).msg_iov = iov.as_ptr() as *mut iovec;
854             (*p).msg_iovlen = iov.len() as _;
855             (*p).msg_control = msg_control as *mut c_void;
856             (*p).msg_controllen = msg_controllen as _;
857             (*p).msg_flags = 0;
858             mhdr.assume_init()
859         }
860     };
861 
862     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
863 
864     Errno::result(ret).map(|r| {
865         let cmsghdr = unsafe {
866             if mhdr.msg_controllen > 0 {
867                 // got control message(s)
868                 cmsg_buffer
869                     .as_mut()
870                     .unwrap()
871                     .set_len(mhdr.msg_controllen as usize);
872                 debug_assert!(!mhdr.msg_control.is_null());
873                 debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
874                 CMSG_FIRSTHDR(&mhdr as *const msghdr)
875             } else {
876                 ptr::null()
877             }.as_ref()
878         };
879 
880         let address = unsafe {
881             sockaddr_storage_to_addr(&address.assume_init(),
882                                      mhdr.msg_namelen as usize
883             ).ok()
884         };
885         RecvMsg {
886             bytes: r as usize,
887             cmsghdr,
888             address,
889             flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
890             mhdr,
891         }
892     })
893 }
894 
895 
896 /// Create an endpoint for communication
897 ///
898 /// The `protocol` specifies a particular protocol to be used with the
899 /// socket.  Normally only a single protocol exists to support a
900 /// particular socket type within a given protocol family, in which case
901 /// protocol can be specified as `None`.  However, it is possible that many
902 /// protocols may exist, in which case a particular protocol must be
903 /// specified in this manner.
904 ///
905 /// [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>906 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
907     let protocol = match protocol.into() {
908         None => 0,
909         Some(p) => p as c_int,
910     };
911 
912     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
913     // little easier to understand by separating it out. So we have to merge these bitfields
914     // here.
915     let mut ty = ty as c_int;
916     ty |= flags.bits();
917 
918     let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
919 
920     Errno::result(res)
921 }
922 
923 /// Create a pair of connected sockets
924 ///
925 /// [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)>926 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
927                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
928     let protocol = match protocol.into() {
929         None => 0,
930         Some(p) => p as c_int,
931     };
932 
933     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
934     // little easier to understand by separating it out. So we have to merge these bitfields
935     // here.
936     let mut ty = ty as c_int;
937     ty |= flags.bits();
938 
939     let mut fds = [-1, -1];
940 
941     let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
942     Errno::result(res)?;
943 
944     Ok((fds[0], fds[1]))
945 }
946 
947 /// Listen for connections on a socket
948 ///
949 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
listen(sockfd: RawFd, backlog: usize) -> Result<()>950 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
951     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
952 
953     Errno::result(res).map(drop)
954 }
955 
956 /// Bind a name to a socket
957 ///
958 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
bind(fd: RawFd, addr: &SockAddr) -> Result<()>959 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
960     let res = unsafe {
961         let (ptr, len) = addr.as_ffi_pair();
962         libc::bind(fd, ptr, len)
963     };
964 
965     Errno::result(res).map(drop)
966 }
967 
968 /// Accept a connection on a socket
969 ///
970 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
accept(sockfd: RawFd) -> Result<RawFd>971 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
972     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
973 
974     Errno::result(res)
975 }
976 
977 /// Accept a connection on a socket
978 ///
979 /// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
980 #[cfg(any(target_os = "android",
981           target_os = "freebsd",
982           target_os = "linux",
983           target_os = "openbsd"))]
accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd>984 pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
985     let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
986 
987     Errno::result(res)
988 }
989 
990 /// Initiate a connection on a socket
991 ///
992 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
connect(fd: RawFd, addr: &SockAddr) -> Result<()>993 pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
994     let res = unsafe {
995         let (ptr, len) = addr.as_ffi_pair();
996         libc::connect(fd, ptr, len)
997     };
998 
999     Errno::result(res).map(drop)
1000 }
1001 
1002 /// Receive data from a connection-oriented socket. Returns the number of
1003 /// bytes read
1004 ///
1005 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize>1006 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
1007     unsafe {
1008         let ret = libc::recv(
1009             sockfd,
1010             buf.as_ptr() as *mut c_void,
1011             buf.len() as size_t,
1012             flags.bits());
1013 
1014         Errno::result(ret).map(|r| r as usize)
1015     }
1016 }
1017 
1018 /// Receive data from a connectionless or connection-oriented socket. Returns
1019 /// the number of bytes read and, for connectionless sockets,  the socket
1020 /// address of the sender.
1021 ///
1022 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, Option<SockAddr>)>1023 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
1024     -> Result<(usize, Option<SockAddr>)>
1025 {
1026     unsafe {
1027         let mut addr: sockaddr_storage = mem::zeroed();
1028         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1029 
1030         let ret = Errno::result(libc::recvfrom(
1031             sockfd,
1032             buf.as_ptr() as *mut c_void,
1033             buf.len() as size_t,
1034             0,
1035             &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
1036             &mut len as *mut socklen_t))? as usize;
1037 
1038         match sockaddr_storage_to_addr(&addr, len as usize) {
1039             Err(Error::Sys(Errno::ENOTCONN)) => Ok((ret, None)),
1040             Ok(addr) => Ok((ret, Some(addr))),
1041             Err(e) => Err(e)
1042         }
1043     }
1044 }
1045 
1046 /// Send a message to a socket
1047 ///
1048 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize>1049 pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
1050     let ret = unsafe {
1051         let (ptr, len) = addr.as_ffi_pair();
1052         libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
1053     };
1054 
1055     Errno::result(ret).map(|r| r as usize)
1056 }
1057 
1058 /// Send data to a connection-oriented socket. Returns the number of bytes read
1059 ///
1060 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize>1061 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
1062     let ret = unsafe {
1063         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
1064     };
1065 
1066     Errno::result(ret).map(|r| r as usize)
1067 }
1068 
1069 /*
1070  *
1071  * ===== Socket Options =====
1072  *
1073  */
1074 
1075 /// The protocol level at which to get / set socket options. Used as an
1076 /// argument to `getsockopt` and `setsockopt`.
1077 ///
1078 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
1079 #[repr(i32)]
1080 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1081 pub enum SockLevel {
1082     Socket = libc::SOL_SOCKET,
1083     Tcp = libc::IPPROTO_TCP,
1084     Ip = libc::IPPROTO_IP,
1085     Ipv6 = libc::IPPROTO_IPV6,
1086     Udp = libc::IPPROTO_UDP,
1087     #[cfg(any(target_os = "android", target_os = "linux"))]
1088     Netlink = libc::SOL_NETLINK,
1089     #[cfg(any(target_os = "android", target_os = "linux"))]
1090     Alg = libc::SOL_ALG,
1091 }
1092 
1093 /// Represents a socket option that can be accessed or set. Used as an argument
1094 /// to `getsockopt`
1095 pub trait GetSockOpt : Copy {
1096     type Val;
1097 
1098     #[doc(hidden)]
get(&self, fd: RawFd) -> Result<Self::Val>1099     fn get(&self, fd: RawFd) -> Result<Self::Val>;
1100 }
1101 
1102 /// Represents a socket option that can be accessed or set. Used as an argument
1103 /// to `setsockopt`
1104 pub trait SetSockOpt : Clone {
1105     type Val;
1106 
1107     #[doc(hidden)]
set(&self, fd: RawFd, val: &Self::Val) -> Result<()>1108     fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
1109 }
1110 
1111 /// Get the current value for the requested socket option
1112 ///
1113 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val>1114 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
1115     opt.get(fd)
1116 }
1117 
1118 /// Sets the value for the requested socket option
1119 ///
1120 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
1121 ///
1122 /// # Examples
1123 ///
1124 /// ```
1125 /// use nix::sys::socket::setsockopt;
1126 /// use nix::sys::socket::sockopt::KeepAlive;
1127 /// use std::net::TcpListener;
1128 /// use std::os::unix::io::AsRawFd;
1129 ///
1130 /// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
1131 /// let fd = listener.as_raw_fd();
1132 /// let res = setsockopt(fd, KeepAlive, &true);
1133 /// assert!(res.is_ok());
1134 /// ```
setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>1135 pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
1136     opt.set(fd, val)
1137 }
1138 
1139 /// Get the address of the peer connected to the socket `fd`.
1140 ///
1141 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
getpeername(fd: RawFd) -> Result<SockAddr>1142 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
1143     unsafe {
1144         let mut addr = mem::MaybeUninit::uninit();
1145         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1146 
1147         let ret = libc::getpeername(
1148             fd,
1149             addr.as_mut_ptr() as *mut libc::sockaddr,
1150             &mut len
1151         );
1152 
1153         Errno::result(ret)?;
1154 
1155         sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
1156     }
1157 }
1158 
1159 /// Get the current address to which the socket `fd` is bound.
1160 ///
1161 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
getsockname(fd: RawFd) -> Result<SockAddr>1162 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
1163     unsafe {
1164         let mut addr = mem::MaybeUninit::uninit();
1165         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1166 
1167         let ret = libc::getsockname(
1168             fd,
1169             addr.as_mut_ptr() as *mut libc::sockaddr,
1170             &mut len
1171         );
1172 
1173         Errno::result(ret)?;
1174 
1175         sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
1176     }
1177 }
1178 
1179 /// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
1180 /// size.  In C this would usually be done by casting.  The `len` argument
1181 /// should be the number of bytes in the `sockaddr_storage` that are actually
1182 /// allocated and valid.  It must be at least as large as all the useful parts
1183 /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
1184 /// include the terminating null.
sockaddr_storage_to_addr( addr: &sockaddr_storage, len: usize) -> Result<SockAddr>1185 pub unsafe fn sockaddr_storage_to_addr(
1186     addr: &sockaddr_storage,
1187     len: usize) -> Result<SockAddr> {
1188 
1189     if len < mem::size_of_val(&addr.ss_family) {
1190         return Err(Error::Sys(Errno::ENOTCONN));
1191     }
1192 
1193     match c_int::from(addr.ss_family) {
1194         libc::AF_INET => {
1195             assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
1196             let ret = *(addr as *const _ as *const sockaddr_in);
1197             Ok(SockAddr::Inet(InetAddr::V4(ret)))
1198         }
1199         libc::AF_INET6 => {
1200             assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
1201             Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
1202         }
1203         libc::AF_UNIX => {
1204             let sun = *(addr as *const _ as *const sockaddr_un);
1205             let pathlen = len - offset_of!(sockaddr_un, sun_path);
1206             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
1207         }
1208         #[cfg(any(target_os = "android", target_os = "linux"))]
1209         libc::AF_NETLINK => {
1210             use libc::sockaddr_nl;
1211             Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
1212         }
1213         #[cfg(any(target_os = "android", target_os = "linux"))]
1214         libc::AF_ALG => {
1215             use libc::sockaddr_alg;
1216             Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
1217         }
1218         #[cfg(target_os = "linux")]
1219         libc::AF_VSOCK => {
1220             use libc::sockaddr_vm;
1221             Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
1222         }
1223         af => panic!("unexpected address family {}", af),
1224     }
1225 }
1226 
1227 
1228 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1229 pub enum Shutdown {
1230     /// Further receptions will be disallowed.
1231     Read,
1232     /// Further  transmissions will be disallowed.
1233     Write,
1234     /// Further receptions and transmissions will be disallowed.
1235     Both,
1236 }
1237 
1238 /// Shut down part of a full-duplex connection.
1239 ///
1240 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
shutdown(df: RawFd, how: Shutdown) -> Result<()>1241 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
1242     unsafe {
1243         use libc::shutdown;
1244 
1245         let how = match how {
1246             Shutdown::Read  => libc::SHUT_RD,
1247             Shutdown::Write => libc::SHUT_WR,
1248             Shutdown::Both  => libc::SHUT_RDWR,
1249         };
1250 
1251         Errno::result(shutdown(df, how)).map(drop)
1252     }
1253 }
1254