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