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 features;
7 use libc::{self, c_void, c_int, socklen_t, size_t};
8 use std::{fmt, 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 = "linux", target_os = "android"))]
33 pub use ::sys::socket::addr::netlink::NetlinkAddr;
34 
35 pub use libc::{
36     cmsghdr,
37     msghdr,
38     sa_family_t,
39     sockaddr,
40     sockaddr_in,
41     sockaddr_in6,
42     sockaddr_storage,
43     sockaddr_un,
44 };
45 
46 /// These constants are used to specify the communication semantics
47 /// when creating a socket with [`socket()`](fn.socket.html)
48 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
49 #[repr(i32)]
50 pub enum SockType {
51     /// Provides sequenced, reliable, two-way, connection-
52     /// based byte streams.  An out-of-band data transmission
53     /// mechanism may be supported.
54     Stream = libc::SOCK_STREAM,
55     /// Supports datagrams (connectionless, unreliable
56     /// messages of a fixed maximum length).
57     Datagram = libc::SOCK_DGRAM,
58     /// Provides a sequenced, reliable, two-way connection-
59     /// based data transmission path for datagrams of fixed
60     /// maximum length; a consumer is required to read an
61     /// entire packet with each input system call.
62     SeqPacket = libc::SOCK_SEQPACKET,
63     /// Provides raw network protocol access.
64     Raw = libc::SOCK_RAW,
65     /// Provides a reliable datagram layer that does not
66     /// guarantee ordering.
67     Rdm = libc::SOCK_RDM,
68 }
69 
70 /// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
71 /// to specify the protocol to use.
72 #[repr(i32)]
73 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
74 pub enum SockProtocol {
75     /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
76     Tcp = libc::IPPROTO_TCP,
77     /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
78     Udp = libc::IPPROTO_UDP,
79     /// Allows applications and other KEXTs to be notified when certain kernel events occur
80     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
81     #[cfg(any(target_os = "ios", target_os = "macos"))]
82     KextEvent = libc::SYSPROTO_EVENT,
83     /// Allows applications to configure and control a KEXT
84     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
85     #[cfg(any(target_os = "ios", target_os = "macos"))]
86     KextControl = libc::SYSPROTO_CONTROL,
87 }
88 
89 libc_bitflags!{
90     /// Additional socket options
91     pub struct SockFlag: c_int {
92         /// Set non-blocking mode on the new socket
93         #[cfg(any(target_os = "android",
94                   target_os = "dragonfly",
95                   target_os = "freebsd",
96                   target_os = "linux",
97                   target_os = "netbsd",
98                   target_os = "openbsd"))]
99         SOCK_NONBLOCK;
100         /// Set close-on-exec on the new descriptor
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_CLOEXEC;
108         /// Return `EPIPE` instead of raising `SIGPIPE`
109         #[cfg(target_os = "netbsd")]
110         SOCK_NOSIGPIPE;
111         /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
112         /// to the DNS port (typically 53)
113         #[cfg(target_os = "openbsd")]
114         SOCK_DNS;
115     }
116 }
117 
118 libc_bitflags!{
119     /// Flags for send/recv and their relatives
120     pub struct MsgFlags: libc::c_int {
121         /// Sends or requests out-of-band data on sockets that support this notion
122         /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
123         /// support out-of-band data.
124         MSG_OOB;
125         /// Peeks at an incoming message. The data is treated as unread and the next
126         /// [`recv()`](fn.recv.html)
127         /// or similar function shall still return this data.
128         MSG_PEEK;
129         /// Enables nonblocking operation; if the operation would block,
130         /// `EAGAIN` or `EWOULDBLOCK` is returned.  This provides similar
131         /// behavior to setting the `O_NONBLOCK` flag
132         /// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
133         /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
134         /// call option, whereas `O_NONBLOCK` is a setting on the open file
135         /// description (see [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)),
136         /// which will affect all threads in
137         /// the calling process and as well as other processes that hold
138         /// file descriptors referring to the same open file description.
139         MSG_DONTWAIT;
140         /// Receive flags: Control Data was discarded (buffer too small)
141         MSG_CTRUNC;
142         /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
143         /// (since Linux 2.4.27/2.6.8),
144         /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
145         /// sockets: return the real length of the packet or datagram, even
146         /// when it was longer than the passed buffer. Not implemented for UNIX
147         /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
148         ///
149         /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
150         MSG_TRUNC;
151         /// Terminates a record (when this notion is supported, as for
152         /// sockets of type [`SeqPacket`](enum.SockType.html)).
153         MSG_EOR;
154         /// This flag specifies that queued errors should be received from
155         /// the socket error queue. (For more details, see
156         /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
157         #[cfg(any(target_os = "linux", target_os = "android"))]
158         MSG_ERRQUEUE;
159         /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
160         /// file descriptor using the `SCM_RIGHTS` operation (described in
161         /// [unix(7)](https://linux.die.net/man/7/unix)).
162         /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
163         /// [open(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
164         ///
165         /// Only used in [`recvmsg`](fn.recvmsg.html) function.
166         #[cfg(any(target_os = "linux", target_os = "android"))]
167         MSG_CMSG_CLOEXEC;
168     }
169 }
170 
171 cfg_if! {
172     if #[cfg(all(target_os = "linux", not(target_arch = "arm")))] {
173         /// Unix credentials of the sending process.
174         ///
175         /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
176         #[repr(C)]
177         #[derive(Clone, Copy)]
178         pub struct UnixCredentials(libc::ucred);
179 
180         impl UnixCredentials {
181             /// Returns the process identifier
182             pub fn pid(&self) -> libc::pid_t {
183                 self.0.pid
184             }
185 
186             /// Returns the user identifier
187             pub fn uid(&self) -> libc::uid_t {
188                 self.0.uid
189             }
190 
191             /// Returns the group identifier
192             pub fn gid(&self) -> libc::gid_t {
193                 self.0.gid
194             }
195         }
196 
197         impl PartialEq for UnixCredentials {
198             fn eq(&self, other: &Self) -> bool {
199                 self.0.pid == other.0.pid && self.0.uid == other.0.uid && self.0.gid == other.0.gid
200             }
201         }
202         impl Eq for UnixCredentials {}
203 
204         impl fmt::Debug for UnixCredentials {
205             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
206                 f.debug_struct("UnixCredentials")
207                     .field("pid", &self.0.pid)
208                     .field("uid", &self.0.uid)
209                     .field("gid", &self.0.gid)
210                     .finish()
211             }
212         }
213     }
214 }
215 
216 /// Request for multicast socket operations
217 ///
218 /// This is a wrapper type around `ip_mreq`.
219 #[repr(C)]
220 #[derive(Clone, Copy)]
221 pub struct IpMembershipRequest(libc::ip_mreq);
222 
223 impl IpMembershipRequest {
224     /// Instantiate a new `IpMembershipRequest`
225     ///
226     /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self227     pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
228         IpMembershipRequest(libc::ip_mreq {
229             imr_multiaddr: group.0,
230             imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
231         })
232     }
233 }
234 
235 impl PartialEq for IpMembershipRequest {
eq(&self, other: &Self) -> bool236     fn eq(&self, other: &Self) -> bool {
237         self.0.imr_multiaddr.s_addr == other.0.imr_multiaddr.s_addr
238             && self.0.imr_interface.s_addr == other.0.imr_interface.s_addr
239     }
240 }
241 impl Eq for IpMembershipRequest {}
242 
243 impl fmt::Debug for IpMembershipRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result244     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245         f.debug_struct("IpMembershipRequest")
246             .field("imr_multiaddr", &self.0.imr_multiaddr.s_addr)
247             .field("imr_interface", &self.0.imr_interface.s_addr)
248             .finish()
249     }
250 }
251 
252 /// Request for ipv6 multicast socket operations
253 ///
254 /// This is a wrapper type around `ipv6_mreq`.
255 #[repr(C)]
256 #[derive(Clone, Copy)]
257 pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
258 
259 impl Ipv6MembershipRequest {
260     /// Instantiate a new `Ipv6MembershipRequest`
new(group: Ipv6Addr) -> Self261     pub fn new(group: Ipv6Addr) -> Self {
262         Ipv6MembershipRequest(libc::ipv6_mreq {
263             ipv6mr_multiaddr: group.0,
264             ipv6mr_interface: 0,
265         })
266     }
267 }
268 
269 impl PartialEq for Ipv6MembershipRequest {
eq(&self, other: &Self) -> bool270     fn eq(&self, other: &Self) -> bool {
271         self.0.ipv6mr_multiaddr.s6_addr == other.0.ipv6mr_multiaddr.s6_addr &&
272             self.0.ipv6mr_interface == other.0.ipv6mr_interface
273     }
274 }
275 impl Eq for Ipv6MembershipRequest {}
276 
277 impl fmt::Debug for Ipv6MembershipRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result278     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279         f.debug_struct("Ipv6MembershipRequest")
280             .field("ipv6mr_multiaddr", &self.0.ipv6mr_multiaddr.s6_addr)
281             .field("ipv6mr_interface", &self.0.ipv6mr_interface)
282             .finish()
283     }
284 }
285 
286 /// Copy the in-memory representation of src into the byte slice dst,
287 /// updating the slice to point to the remainder of dst only. Unsafe
288 /// because it exposes all bytes in src, which may be UB if some of them
289 /// are uninitialized (including padding).
copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8])290 unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
291     let srclen = mem::size_of_val(src);
292     let mut tmpdst = &mut [][..];
293     mem::swap(&mut tmpdst, dst);
294     let (target, mut remainder) = tmpdst.split_at_mut(srclen);
295     // Safe because the mutable borrow of dst guarantees that src does not alias it.
296     ptr::copy_nonoverlapping(src as *const T as *const u8, target.as_mut_ptr(), srclen);
297     mem::swap(dst, &mut remainder);
298 }
299 
300 cfg_if! {
301     // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
302     if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
303         type align_of_cmsg_data = u32;
304     } else {
305         type align_of_cmsg_data = size_t;
306     }
307 }
308 
309 /// A structure used to make room in a cmsghdr passed to recvmsg. The
310 /// size and alignment match that of a cmsghdr followed by a T, but the
311 /// fields are not accessible, as the actual types will change on a call
312 /// to recvmsg.
313 ///
314 /// To make room for multiple messages, nest the type parameter with
315 /// tuples:
316 ///
317 /// ```
318 /// use std::os::unix::io::RawFd;
319 /// use nix::sys::socket::CmsgSpace;
320 /// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
321 /// ```
322 #[repr(C)]
323 pub struct CmsgSpace<T> {
324     _hdr: cmsghdr,
325     _pad: [align_of_cmsg_data; 0],
326     _data: T,
327 }
328 
329 impl<T> CmsgSpace<T> {
330     /// Create a CmsgSpace<T>. The structure is used only for space, so
331     /// the fields are uninitialized.
new() -> Self332     pub fn new() -> Self {
333         // Safe because the fields themselves aren't accessible.
334         unsafe { mem::uninitialized() }
335     }
336 }
337 
338 pub struct RecvMsg<'a> {
339     // The number of bytes received.
340     pub bytes: usize,
341     cmsg_buffer: &'a [u8],
342     pub address: Option<SockAddr>,
343     pub flags: MsgFlags,
344 }
345 
346 impl<'a> RecvMsg<'a> {
347     /// Iterate over the valid control messages pointed to by this
348     /// msghdr.
cmsgs(&self) -> CmsgIterator349     pub fn cmsgs(&self) -> CmsgIterator {
350         CmsgIterator {
351             buf: self.cmsg_buffer,
352             next: 0
353         }
354     }
355 }
356 
357 pub struct CmsgIterator<'a> {
358     buf: &'a [u8],
359     next: usize,
360 }
361 
362 impl<'a> Iterator for CmsgIterator<'a> {
363     type Item = ControlMessage<'a>;
364 
365     // The implementation loosely follows CMSG_FIRSTHDR / CMSG_NXTHDR,
366     // although we handle the invariants in slightly different places to
367     // get a better iterator interface.
next(&mut self) -> Option<ControlMessage<'a>>368     fn next(&mut self) -> Option<ControlMessage<'a>> {
369         let sizeof_cmsghdr = mem::size_of::<cmsghdr>();
370         if self.buf.len() < sizeof_cmsghdr {
371             return None;
372         }
373         let cmsg: &'a cmsghdr = unsafe { &*(self.buf.as_ptr() as *const cmsghdr) };
374 
375         // This check is only in the glibc implementation of CMSG_NXTHDR
376         // (although it claims the kernel header checks this), but such
377         // a structure is clearly invalid, either way.
378         let cmsg_len = cmsg.cmsg_len as usize;
379         if cmsg_len < sizeof_cmsghdr {
380             return None;
381         }
382         let len = cmsg_len - sizeof_cmsghdr;
383         let aligned_cmsg_len = if self.next == 0 {
384             // CMSG_FIRSTHDR
385             cmsg_len
386         } else {
387             // CMSG_NXTHDR
388             cmsg_align(cmsg_len)
389         };
390 
391         // Advance our internal pointer.
392         if aligned_cmsg_len > self.buf.len() {
393             return None;
394         }
395         let cmsg_data = &self.buf[cmsg_align(sizeof_cmsghdr)..cmsg_len];
396         self.buf = &self.buf[aligned_cmsg_len..];
397         self.next += 1;
398 
399         match (cmsg.cmsg_level, cmsg.cmsg_type) {
400             (libc::SOL_SOCKET, libc::SCM_RIGHTS) => unsafe {
401                 Some(ControlMessage::ScmRights(
402                     slice::from_raw_parts(cmsg_data.as_ptr() as *const _,
403                                           cmsg_data.len() / mem::size_of::<RawFd>())))
404             },
405             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => unsafe {
406                 Some(ControlMessage::ScmTimestamp(
407                     &*(cmsg_data.as_ptr() as *const _)))
408             },
409             (_, _) => unsafe {
410                 Some(ControlMessage::Unknown(UnknownCmsg(
411                     cmsg,
412                     slice::from_raw_parts(
413                         cmsg_data.as_ptr() as *const _,
414                         len))))
415             }
416         }
417     }
418 }
419 
420 /// A type-safe wrapper around a single control message. More types may
421 /// be added to this enum; do not exhaustively pattern-match it.
422 /// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
423 pub enum ControlMessage<'a> {
424     /// A message of type `SCM_RIGHTS`, containing an array of file
425     /// descriptors passed between processes.
426     ///
427     /// See the description in the "Ancillary messages" section of the
428     /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
429     ScmRights(&'a [RawFd]),
430     /// A message of type `SCM_TIMESTAMP`, containing the time the
431     /// packet was received by the kernel.
432     ///
433     /// See the kernel's explanation in "SO_TIMESTAMP" of
434     /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
435     ///
436     /// # Examples
437     ///
438     // Disable this test on FreeBSD i386
439     // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
440     #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
441     #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
442     /// use nix::sys::socket::*;
443     /// use nix::sys::uio::IoVec;
444     /// use nix::sys::time::*;
445     /// use std::time::*;
446     ///
447     /// // Set up
448     /// let message1 = "Ohayō!".as_bytes();
449     /// let message2 = "Jā ne".as_bytes();
450     /// let in_socket = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
451     /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
452     /// bind(in_socket, &SockAddr::new_inet(InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0))).unwrap();
453     /// let address = if let Ok(address) = getsockname(in_socket) { address } else { unreachable!() };
454     ///
455     /// // Send both
456     /// assert!(Ok(message1.len()) == sendmsg(in_socket, &[IoVec::from_slice(message1)], &[], MsgFlags::empty(), Some(&address)));
457     /// let time = SystemTime::now();
458     /// std::thread::sleep(Duration::from_millis(250));
459     /// assert!(Ok(message2.len()) == sendmsg(in_socket, &[IoVec::from_slice(message2)], &[], MsgFlags::empty(), Some(&address)));
460     /// let delay = time.elapsed().unwrap();
461     ///
462     /// // Receive the first
463     /// let mut buffer1 = vec![0u8; message1.len() + message2.len()];
464     /// let mut time1: CmsgSpace<TimeVal> = CmsgSpace::new();
465     /// let received1 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer1)], Some(&mut time1), MsgFlags::empty()).unwrap();
466     /// let mut time1 = if let Some(ControlMessage::ScmTimestamp(&time1)) = received1.cmsgs().next() { time1 } else { panic!("Unexpected or no control message") };
467     ///
468     /// // Receive the second
469     /// let mut buffer2 = vec![0u8; message1.len() + message2.len()];
470     /// let mut time2: CmsgSpace<TimeVal> = CmsgSpace::new();
471     /// let received2 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer2)], Some(&mut time2), MsgFlags::empty()).unwrap();
472     /// let mut time2 = if let Some(ControlMessage::ScmTimestamp(&time2)) = received2.cmsgs().next() { time2 } else { panic!("Unexpected or no control message") };
473     ///
474     /// // Swap if needed; UDP is unordered
475     /// match (received1.bytes, received2.bytes, message1.len(), message2.len()) {
476     ///     (l1, l2, m1, m2) if l1 == m1 && l2 == m2 => {},
477     ///     (l2, l1, m1, m2) if l1 == m1 && l2 == m2 => {
478     ///         std::mem::swap(&mut time1, &mut time2);
479     ///         std::mem::swap(&mut buffer1, &mut buffer2);
480     ///     },
481     ///     _ => panic!("Wrong packets"),
482     /// };
483     ///
484     /// // Compare results
485     /// println!("{:?} @ {:?}, {:?} @ {:?}, {:?}", buffer1, time1, buffer2, time2, delay);
486     /// assert!(message1 == &buffer1[0..(message1.len())], "{:?} == {:?}", message1, buffer1);
487     /// assert!(message2 == &buffer2[0..(message2.len())], "{:?} == {:?}", message2, buffer2);
488     /// let time = time2 - time1;
489     /// let time = Duration::new(time.num_seconds() as u64, time.num_nanoseconds() as u32);
490     /// let difference = if delay < time { time - delay } else { delay - time };
491     /// assert!(difference.subsec_nanos() < 5_000_000, "{}ns < 5ms", difference.subsec_nanos());
492     /// assert!(difference.as_secs() == 0);
493     ///
494     /// // Close socket
495     /// nix::unistd::close(in_socket).unwrap();
496     /// ```
497     ScmTimestamp(&'a TimeVal),
498     #[doc(hidden)]
499     Unknown(UnknownCmsg<'a>),
500 }
501 
502 // An opaque structure used to prevent cmsghdr from being a public type
503 #[doc(hidden)]
504 pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
505 
506 // Round `len` up to meet the platform's required alignment for
507 // `cmsghdr`s and trailing `cmsghdr` data.  This should match the
508 // behaviour of CMSG_ALIGN from the Linux headers and do the correct
509 // thing on other platforms that don't usually provide CMSG_ALIGN.
510 #[inline]
cmsg_align(len: usize) -> usize511 fn cmsg_align(len: usize) -> usize {
512     let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
513     (len + align_bytes) & !align_bytes
514 }
515 
516 impl<'a> ControlMessage<'a> {
517     /// The value of CMSG_SPACE on this message.
space(&self) -> usize518     fn space(&self) -> usize {
519         cmsg_align(self.len())
520     }
521 
522     /// The value of CMSG_LEN on this message.
len(&self) -> usize523     fn len(&self) -> usize {
524         cmsg_align(mem::size_of::<cmsghdr>()) + match *self {
525             ControlMessage::ScmRights(fds) => {
526                 mem::size_of_val(fds)
527             },
528             ControlMessage::ScmTimestamp(t) => {
529                 mem::size_of_val(t)
530             },
531             ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
532                 mem::size_of_val(bytes)
533             }
534         }
535     }
536 
537     // Unsafe: start and end of buffer must be cmsg_align'd. Updates
538     // the provided slice; panics if the buffer is too small.
encode_into<'b>(&self, buf: &mut &'b mut [u8])539     unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
540         match *self {
541             ControlMessage::ScmRights(fds) => {
542                 let cmsg = cmsghdr {
543                     cmsg_len: self.len() as _,
544                     cmsg_level: libc::SOL_SOCKET,
545                     cmsg_type: libc::SCM_RIGHTS,
546                     ..mem::uninitialized()
547                 };
548                 copy_bytes(&cmsg, buf);
549 
550                 let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
551                     mem::size_of_val(&cmsg);
552 
553                 let mut tmpbuf = &mut [][..];
554                 mem::swap(&mut tmpbuf, buf);
555                 let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
556                 mem::swap(buf, &mut remainder);
557 
558                 copy_bytes(fds, buf);
559             },
560             ControlMessage::ScmTimestamp(t) => {
561                 let cmsg = cmsghdr {
562                     cmsg_len: self.len() as _,
563                     cmsg_level: libc::SOL_SOCKET,
564                     cmsg_type: libc::SCM_TIMESTAMP,
565                     ..mem::uninitialized()
566                 };
567                 copy_bytes(&cmsg, buf);
568 
569                 let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
570                     mem::size_of_val(&cmsg);
571 
572                 let mut tmpbuf = &mut [][..];
573                 mem::swap(&mut tmpbuf, buf);
574                 let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
575                 mem::swap(buf, &mut remainder);
576 
577                 copy_bytes(t, buf);
578             },
579             ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
580                 copy_bytes(orig_cmsg, buf);
581                 copy_bytes(bytes, buf);
582             }
583         }
584     }
585 }
586 
587 
588 /// Send data in scatter-gather vectors to a socket, possibly accompanied
589 /// by ancillary data. Optionally direct the message at the given address,
590 /// as with sendto.
591 ///
592 /// Allocates if cmsgs is nonempty.
sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'a>], flags: MsgFlags, addr: Option<&'a SockAddr>) -> Result<usize>593 pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'a>], flags: MsgFlags, addr: Option<&'a SockAddr>) -> Result<usize> {
594     let mut len = 0;
595     let mut capacity = 0;
596     for cmsg in cmsgs {
597         len += cmsg.len();
598         capacity += cmsg.space();
599     }
600     // Note that the resulting vector claims to have length == capacity,
601     // so it's presently uninitialized.
602     let mut cmsg_buffer = unsafe {
603         let mut vec = Vec::<u8>::with_capacity(len);
604         vec.set_len(len);
605         vec
606     };
607     {
608         let mut ptr = &mut cmsg_buffer[..];
609         for cmsg in cmsgs {
610             unsafe { cmsg.encode_into(&mut ptr) };
611         }
612     }
613 
614     let (name, namelen) = match addr {
615         Some(addr) => { let (x, y) = unsafe { addr.as_ffi_pair() }; (x as *const _, y) }
616         None => (ptr::null(), 0),
617     };
618 
619     let cmsg_ptr = if capacity > 0 {
620         cmsg_buffer.as_ptr() as *const c_void
621     } else {
622         ptr::null()
623     };
624 
625     let mhdr = unsafe {
626         let mut mhdr: msghdr = mem::uninitialized();
627         mhdr.msg_name =  name as *mut _;
628         mhdr.msg_namelen =  namelen;
629         mhdr.msg_iov =  iov.as_ptr() as *mut _;
630         mhdr.msg_iovlen =  iov.len() as _;
631         mhdr.msg_control =  cmsg_ptr as *mut _;
632         mhdr.msg_controllen =  capacity as _;
633         mhdr.msg_flags =  0;
634         mhdr
635     };
636     let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
637 
638     Errno::result(ret).map(|r| r as usize)
639 }
640 
641 /// Receive message in scatter-gather vectors from a socket, and
642 /// optionally receive ancillary data into the provided buffer.
643 /// If no ancillary data is desired, use () as the type parameter.
recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&'a mut CmsgSpace<T>>, flags: MsgFlags) -> Result<RecvMsg<'a>>644 pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&'a mut CmsgSpace<T>>, flags: MsgFlags) -> Result<RecvMsg<'a>> {
645     let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
646     let (msg_control, msg_controllen) = match cmsg_buffer {
647         Some(cmsg_buffer) => (cmsg_buffer as *mut _, mem::size_of_val(cmsg_buffer)),
648         None => (ptr::null_mut(), 0),
649     };
650     let mut mhdr = unsafe {
651         let mut mhdr: msghdr = mem::uninitialized();
652         mhdr.msg_name =  &mut address as *mut _ as *mut _;
653         mhdr.msg_namelen =  mem::size_of::<sockaddr_storage>() as socklen_t;
654         mhdr.msg_iov =  iov.as_ptr() as *mut _;
655         mhdr.msg_iovlen =  iov.len() as _;
656         mhdr.msg_control =  msg_control as *mut _;
657         mhdr.msg_controllen =  msg_controllen as _;
658         mhdr.msg_flags =  0;
659         mhdr
660     };
661     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
662 
663     Ok(unsafe { RecvMsg {
664         bytes: try!(Errno::result(ret)) as usize,
665         cmsg_buffer: slice::from_raw_parts(mhdr.msg_control as *const u8,
666                                            mhdr.msg_controllen as usize),
667         address: sockaddr_storage_to_addr(&address,
668                                           mhdr.msg_namelen as usize).ok(),
669         flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
670     } })
671 }
672 
673 
674 /// Create an endpoint for communication
675 ///
676 /// The `protocol` specifies a particular protocol to be used with the
677 /// socket.  Normally only a single protocol exists to support a
678 /// particular socket type within a given protocol family, in which case
679 /// protocol can be specified as `None`.  However, it is possible that many
680 /// protocols may exist, in which case a particular protocol must be
681 /// specified in this manner.
682 ///
683 /// [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>684 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
685     let mut ty = ty as c_int;
686     let protocol = match protocol.into() {
687         None => 0,
688         Some(p) => p as c_int,
689     };
690     let feat_atomic = features::socket_atomic_cloexec();
691 
692     if feat_atomic {
693         ty |= flags.bits();
694     }
695 
696     // TODO: Check the kernel version
697     let res = try!(Errno::result(unsafe { libc::socket(domain as c_int, ty, protocol) }));
698 
699     #[cfg(any(target_os = "android",
700               target_os = "dragonfly",
701               target_os = "freebsd",
702               target_os = "linux",
703               target_os = "netbsd",
704               target_os = "openbsd"))]
705     {
706         use fcntl::{fcntl, FdFlag, OFlag};
707         use fcntl::FcntlArg::{F_SETFD, F_SETFL};
708 
709         if !feat_atomic {
710             if flags.contains(SockFlag::SOCK_CLOEXEC) {
711                 try!(fcntl(res, F_SETFD(FdFlag::FD_CLOEXEC)));
712             }
713 
714             if flags.contains(SockFlag::SOCK_NONBLOCK) {
715                 try!(fcntl(res, F_SETFL(OFlag::O_NONBLOCK)));
716             }
717         }
718     }
719 
720     Ok(res)
721 }
722 
723 /// Create a pair of connected sockets
724 ///
725 /// [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)>726 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
727                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
728     let mut ty = ty as c_int;
729     let protocol = match protocol.into() {
730         None => 0,
731         Some(p) => p as c_int,
732     };
733     let feat_atomic = features::socket_atomic_cloexec();
734 
735     if feat_atomic {
736         ty |= flags.bits();
737     }
738     let mut fds = [-1, -1];
739     let res = unsafe {
740         libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
741     };
742     try!(Errno::result(res));
743 
744     #[cfg(any(target_os = "android",
745               target_os = "dragonfly",
746               target_os = "freebsd",
747               target_os = "linux",
748               target_os = "netbsd",
749               target_os = "openbsd"))]
750     {
751         use fcntl::{fcntl, FdFlag, OFlag};
752         use fcntl::FcntlArg::{F_SETFD, F_SETFL};
753 
754         if !feat_atomic {
755             if flags.contains(SockFlag::SOCK_CLOEXEC) {
756                 try!(fcntl(fds[0], F_SETFD(FdFlag::FD_CLOEXEC)));
757                 try!(fcntl(fds[1], F_SETFD(FdFlag::FD_CLOEXEC)));
758             }
759 
760             if flags.contains(SockFlag::SOCK_NONBLOCK) {
761                 try!(fcntl(fds[0], F_SETFL(OFlag::O_NONBLOCK)));
762                 try!(fcntl(fds[1], F_SETFL(OFlag::O_NONBLOCK)));
763             }
764         }
765     }
766     Ok((fds[0], fds[1]))
767 }
768 
769 /// Listen for connections on a socket
770 ///
771 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
listen(sockfd: RawFd, backlog: usize) -> Result<()>772 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
773     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
774 
775     Errno::result(res).map(drop)
776 }
777 
778 /// Bind a name to a socket
779 ///
780 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
781 #[cfg(not(all(target_os="android", target_pointer_width="64")))]
bind(fd: RawFd, addr: &SockAddr) -> Result<()>782 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
783     let res = unsafe {
784         let (ptr, len) = addr.as_ffi_pair();
785         libc::bind(fd, ptr, len)
786     };
787 
788     Errno::result(res).map(drop)
789 }
790 
791 /// Bind a name to a socket
792 ///
793 /// [Further reading](http://man7.org/linux/man-pages/man2/bind.2.html)
794 // Android has some weirdness. Its 64-bit bind takes a c_int instead of a
795 // socklen_t
796 #[cfg(all(target_os="android", target_pointer_width="64"))]
bind(fd: RawFd, addr: &SockAddr) -> Result<()>797 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
798     let res = unsafe {
799         let (ptr, len) = addr.as_ffi_pair();
800         libc::bind(fd, ptr, len as c_int)
801     };
802 
803     Errno::result(res).map(drop)
804 }
805 
806 /// Accept a connection on a socket
807 ///
808 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
accept(sockfd: RawFd) -> Result<RawFd>809 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
810     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
811 
812     Errno::result(res)
813 }
814 
815 /// Accept a connection on a socket
816 ///
817 /// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd>818 pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
819     accept4_polyfill(sockfd, flags)
820 }
821 
822 #[inline]
accept4_polyfill(sockfd: RawFd, flags: SockFlag) -> Result<RawFd>823 fn accept4_polyfill(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
824     let res = try!(Errno::result(unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }));
825 
826     #[cfg(any(target_os = "android",
827               target_os = "dragonfly",
828               target_os = "freebsd",
829               target_os = "linux",
830               target_os = "netbsd",
831               target_os = "openbsd"))]
832     {
833         use fcntl::{fcntl, FdFlag, OFlag};
834         use fcntl::FcntlArg::{F_SETFD, F_SETFL};
835 
836         if flags.contains(SockFlag::SOCK_CLOEXEC) {
837             try!(fcntl(res, F_SETFD(FdFlag::FD_CLOEXEC)));
838         }
839 
840         if flags.contains(SockFlag::SOCK_NONBLOCK) {
841             try!(fcntl(res, F_SETFL(OFlag::O_NONBLOCK)));
842         }
843     }
844 
845     // Disable unused variable warning on some platforms
846     #[cfg(not(any(target_os = "android",
847                   target_os = "dragonfly",
848                   target_os = "freebsd",
849                   target_os = "linux",
850                   target_os = "netbsd",
851                   target_os = "openbsd")))]
852     {
853         let _ = flags;
854     }
855 
856 
857     Ok(res)
858 }
859 
860 /// Initiate a connection on a socket
861 ///
862 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
connect(fd: RawFd, addr: &SockAddr) -> Result<()>863 pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
864     let res = unsafe {
865         let (ptr, len) = addr.as_ffi_pair();
866         libc::connect(fd, ptr, len)
867     };
868 
869     Errno::result(res).map(drop)
870 }
871 
872 /// Receive data from a connection-oriented socket. Returns the number of
873 /// bytes read
874 ///
875 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize>876 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
877     unsafe {
878         let ret = libc::recv(
879             sockfd,
880             buf.as_ptr() as *mut c_void,
881             buf.len() as size_t,
882             flags.bits());
883 
884         Errno::result(ret).map(|r| r as usize)
885     }
886 }
887 
888 /// Receive data from a connectionless or connection-oriented socket. Returns
889 /// the number of bytes read and the socket address of the sender.
890 ///
891 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)>892 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
893     unsafe {
894         let addr: sockaddr_storage = mem::zeroed();
895         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
896 
897         let ret = try!(Errno::result(libc::recvfrom(
898             sockfd,
899             buf.as_ptr() as *mut c_void,
900             buf.len() as size_t,
901             0,
902             mem::transmute(&addr),
903             &mut len as *mut socklen_t)));
904 
905         sockaddr_storage_to_addr(&addr, len as usize)
906             .map(|addr| (ret as usize, addr))
907     }
908 }
909 
910 /// Send a message to a socket
911 ///
912 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize>913 pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
914     let ret = unsafe {
915         let (ptr, len) = addr.as_ffi_pair();
916         libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
917     };
918 
919     Errno::result(ret).map(|r| r as usize)
920 }
921 
922 /// Send data to a connection-oriented socket. Returns the number of bytes read
923 ///
924 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize>925 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
926     let ret = unsafe {
927         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
928     };
929 
930     Errno::result(ret).map(|r| r as usize)
931 }
932 
933 /*
934  *
935  * ===== Socket Options =====
936  *
937  */
938 
939 /// The protocol level at which to get / set socket options. Used as an
940 /// argument to `getsockopt` and `setsockopt`.
941 ///
942 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
943 #[repr(i32)]
944 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
945 pub enum SockLevel {
946     Socket = libc::SOL_SOCKET,
947     Tcp = libc::IPPROTO_TCP,
948     Ip = libc::IPPROTO_IP,
949     Ipv6 = libc::IPPROTO_IPV6,
950     Udp = libc::IPPROTO_UDP,
951     #[cfg(any(target_os = "android", target_os = "linux"))]
952     Netlink = libc::SOL_NETLINK,
953 }
954 
955 /// Represents a socket option that can be accessed or set. Used as an argument
956 /// to `getsockopt`
957 pub trait GetSockOpt : Copy {
958     type Val;
959 
960     #[doc(hidden)]
get(&self, fd: RawFd) -> Result<Self::Val>961     fn get(&self, fd: RawFd) -> Result<Self::Val>;
962 }
963 
964 /// Represents a socket option that can be accessed or set. Used as an argument
965 /// to `setsockopt`
966 pub trait SetSockOpt : Copy {
967     type Val;
968 
969     #[doc(hidden)]
set(&self, fd: RawFd, val: &Self::Val) -> Result<()>970     fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
971 }
972 
973 /// Get the current value for the requested socket option
974 ///
975 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val>976 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
977     opt.get(fd)
978 }
979 
980 /// Sets the value for the requested socket option
981 ///
982 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>983 pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
984     opt.set(fd, val)
985 }
986 
987 /// Get the address of the peer connected to the socket `fd`.
988 ///
989 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
getpeername(fd: RawFd) -> Result<SockAddr>990 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
991     unsafe {
992         let addr: sockaddr_storage = mem::uninitialized();
993         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
994 
995         let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
996 
997         try!(Errno::result(ret));
998 
999         sockaddr_storage_to_addr(&addr, len as usize)
1000     }
1001 }
1002 
1003 /// Get the current address to which the socket `fd` is bound.
1004 ///
1005 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
getsockname(fd: RawFd) -> Result<SockAddr>1006 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
1007     unsafe {
1008         let addr: sockaddr_storage = mem::uninitialized();
1009         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
1010 
1011         let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
1012 
1013         try!(Errno::result(ret));
1014 
1015         sockaddr_storage_to_addr(&addr, len as usize)
1016     }
1017 }
1018 
1019 /// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
1020 /// size.  In C this would usually be done by casting.  The `len` argument
1021 /// should be the number of bytes in the `sockaddr_storage` that are actually
1022 /// allocated and valid.  It must be at least as large as all the useful parts
1023 /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
1024 /// include the terminating null.
sockaddr_storage_to_addr( addr: &sockaddr_storage, len: usize) -> Result<SockAddr>1025 pub unsafe fn sockaddr_storage_to_addr(
1026     addr: &sockaddr_storage,
1027     len: usize) -> Result<SockAddr> {
1028 
1029     if len < mem::size_of_val(&addr.ss_family) {
1030         return Err(Error::Sys(Errno::ENOTCONN));
1031     }
1032 
1033     match addr.ss_family as c_int {
1034         libc::AF_INET => {
1035             assert!(len as usize == mem::size_of::<sockaddr_in>());
1036             let ret = *(addr as *const _ as *const sockaddr_in);
1037             Ok(SockAddr::Inet(InetAddr::V4(ret)))
1038         }
1039         libc::AF_INET6 => {
1040             assert!(len as usize == mem::size_of::<sockaddr_in6>());
1041             Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
1042         }
1043         libc::AF_UNIX => {
1044             let sun = *(addr as *const _ as *const sockaddr_un);
1045             let pathlen = len - offset_of!(sockaddr_un, sun_path);
1046             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
1047         }
1048         #[cfg(any(target_os = "linux", target_os = "android"))]
1049         libc::AF_NETLINK => {
1050             use libc::sockaddr_nl;
1051             Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
1052         }
1053         af => panic!("unexpected address family {}", af),
1054     }
1055 }
1056 
1057 
1058 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1059 pub enum Shutdown {
1060     /// Further receptions will be disallowed.
1061     Read,
1062     /// Further  transmissions will be disallowed.
1063     Write,
1064     /// Further receptions and transmissions will be disallowed.
1065     Both,
1066 }
1067 
1068 /// Shut down part of a full-duplex connection.
1069 ///
1070 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
shutdown(df: RawFd, how: Shutdown) -> Result<()>1071 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
1072     unsafe {
1073         use libc::shutdown;
1074 
1075         let how = match how {
1076             Shutdown::Read  => libc::SHUT_RD,
1077             Shutdown::Write => libc::SHUT_WR,
1078             Shutdown::Both  => libc::SHUT_RDWR,
1079         };
1080 
1081         Errno::result(shutdown(df, how)).map(drop)
1082     }
1083 }
1084