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 = "linux", target_os = "android"))]
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 = "linux", target_os = "android"))]
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(all(target_os = "linux", not(target_arch = "arm")))] {
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 fmt::Debug for UnixCredentials {
209             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210                 f.debug_struct("UnixCredentials")
211                     .field("pid", &self.0.pid)
212                     .field("uid", &self.0.uid)
213                     .field("gid", &self.0.gid)
214                     .finish()
215             }
216         }
217     }
218 }
219 
220 /// Request for multicast socket operations
221 ///
222 /// This is a wrapper type around `ip_mreq`.
223 #[repr(C)]
224 #[derive(Clone, Copy)]
225 pub struct IpMembershipRequest(libc::ip_mreq);
226 
227 impl IpMembershipRequest {
228     /// Instantiate a new `IpMembershipRequest`
229     ///
230     /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self231     pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
232         IpMembershipRequest(libc::ip_mreq {
233             imr_multiaddr: group.0,
234             imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
235         })
236     }
237 }
238 
239 impl PartialEq for IpMembershipRequest {
eq(&self, other: &Self) -> bool240     fn eq(&self, other: &Self) -> bool {
241         self.0.imr_multiaddr.s_addr == other.0.imr_multiaddr.s_addr
242             && self.0.imr_interface.s_addr == other.0.imr_interface.s_addr
243     }
244 }
245 impl Eq for IpMembershipRequest {}
246 
247 impl fmt::Debug for IpMembershipRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result248     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249         f.debug_struct("IpMembershipRequest")
250             .field("imr_multiaddr", &self.0.imr_multiaddr.s_addr)
251             .field("imr_interface", &self.0.imr_interface.s_addr)
252             .finish()
253     }
254 }
255 
256 /// Request for ipv6 multicast socket operations
257 ///
258 /// This is a wrapper type around `ipv6_mreq`.
259 #[repr(C)]
260 #[derive(Clone, Copy)]
261 pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
262 
263 impl Ipv6MembershipRequest {
264     /// Instantiate a new `Ipv6MembershipRequest`
new(group: Ipv6Addr) -> Self265     pub fn new(group: Ipv6Addr) -> Self {
266         Ipv6MembershipRequest(libc::ipv6_mreq {
267             ipv6mr_multiaddr: group.0,
268             ipv6mr_interface: 0,
269         })
270     }
271 }
272 
273 impl PartialEq for Ipv6MembershipRequest {
eq(&self, other: &Self) -> bool274     fn eq(&self, other: &Self) -> bool {
275         self.0.ipv6mr_multiaddr.s6_addr == other.0.ipv6mr_multiaddr.s6_addr &&
276             self.0.ipv6mr_interface == other.0.ipv6mr_interface
277     }
278 }
279 impl Eq for Ipv6MembershipRequest {}
280 
281 impl fmt::Debug for Ipv6MembershipRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result282     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283         f.debug_struct("Ipv6MembershipRequest")
284             .field("ipv6mr_multiaddr", &self.0.ipv6mr_multiaddr.s6_addr)
285             .field("ipv6mr_interface", &self.0.ipv6mr_interface)
286             .finish()
287     }
288 }
289 
290 /// Copy the in-memory representation of src into the byte slice dst,
291 /// updating the slice to point to the remainder of dst only. Unsafe
292 /// because it exposes all bytes in src, which may be UB if some of them
293 /// are uninitialized (including padding).
copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8])294 unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
295     let srclen = mem::size_of_val(src);
296     let mut tmpdst = &mut [][..];
297     mem::swap(&mut tmpdst, dst);
298     let (target, mut remainder) = tmpdst.split_at_mut(srclen);
299     // Safe because the mutable borrow of dst guarantees that src does not alias it.
300     ptr::copy_nonoverlapping(src as *const T as *const u8, target.as_mut_ptr(), srclen);
301     mem::swap(dst, &mut remainder);
302 }
303 
304 cfg_if! {
305     // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
306     if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
307         type align_of_cmsg_data = u32;
308     } else {
309         type align_of_cmsg_data = size_t;
310     }
311 }
312 
313 /// A structure used to make room in a cmsghdr passed to recvmsg. The
314 /// size and alignment match that of a cmsghdr followed by a T, but the
315 /// fields are not accessible, as the actual types will change on a call
316 /// to recvmsg.
317 ///
318 /// To make room for multiple messages, nest the type parameter with
319 /// tuples:
320 ///
321 /// ```
322 /// use std::os::unix::io::RawFd;
323 /// use nix::sys::socket::CmsgSpace;
324 /// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
325 /// ```
326 #[repr(C)]
327 #[allow(missing_debug_implementations)]
328 pub struct CmsgSpace<T> {
329     _hdr: cmsghdr,
330     _pad: [align_of_cmsg_data; 0],
331     _data: T,
332 }
333 
334 impl<T> CmsgSpace<T> {
335     /// Create a CmsgSpace<T>. The structure is used only for space, so
336     /// the fields are uninitialized.
new() -> Self337     pub fn new() -> Self {
338         // Safe because the fields themselves aren't accessible.
339         unsafe { mem::uninitialized() }
340     }
341 }
342 
343 #[allow(missing_debug_implementations)]
344 pub struct RecvMsg<'a> {
345     // The number of bytes received.
346     pub bytes: usize,
347     cmsg_buffer: &'a [u8],
348     pub address: Option<SockAddr>,
349     pub flags: MsgFlags,
350 }
351 
352 impl<'a> RecvMsg<'a> {
353     /// Iterate over the valid control messages pointed to by this
354     /// msghdr.
cmsgs(&self) -> CmsgIterator355     pub fn cmsgs(&self) -> CmsgIterator {
356         CmsgIterator {
357             buf: self.cmsg_buffer,
358             next: 0
359         }
360     }
361 }
362 
363 #[allow(missing_debug_implementations)]
364 pub struct CmsgIterator<'a> {
365     buf: &'a [u8],
366     next: usize,
367 }
368 
369 impl<'a> Iterator for CmsgIterator<'a> {
370     type Item = ControlMessage<'a>;
371 
372     // The implementation loosely follows CMSG_FIRSTHDR / CMSG_NXTHDR,
373     // although we handle the invariants in slightly different places to
374     // get a better iterator interface.
next(&mut self) -> Option<ControlMessage<'a>>375     fn next(&mut self) -> Option<ControlMessage<'a>> {
376         let sizeof_cmsghdr = mem::size_of::<cmsghdr>();
377         if self.buf.len() < sizeof_cmsghdr {
378             return None;
379         }
380         let cmsg: &'a cmsghdr = unsafe { &*(self.buf.as_ptr() as *const cmsghdr) };
381 
382         // This check is only in the glibc implementation of CMSG_NXTHDR
383         // (although it claims the kernel header checks this), but such
384         // a structure is clearly invalid, either way.
385         let cmsg_len = cmsg.cmsg_len as usize;
386         if cmsg_len < sizeof_cmsghdr {
387             return None;
388         }
389         let len = cmsg_len - sizeof_cmsghdr;
390         let aligned_cmsg_len = if self.next == 0 {
391             // CMSG_FIRSTHDR
392             cmsg_len
393         } else {
394             // CMSG_NXTHDR
395             cmsg_align(cmsg_len)
396         };
397 
398         // Advance our internal pointer.
399         if aligned_cmsg_len > self.buf.len() {
400             return None;
401         }
402         let cmsg_data = &self.buf[cmsg_align(sizeof_cmsghdr)..cmsg_len];
403         self.buf = &self.buf[aligned_cmsg_len..];
404         self.next += 1;
405 
406         match (cmsg.cmsg_level, cmsg.cmsg_type) {
407             (libc::SOL_SOCKET, libc::SCM_RIGHTS) => unsafe {
408                 Some(ControlMessage::ScmRights(
409                     slice::from_raw_parts(cmsg_data.as_ptr() as *const _,
410                                           cmsg_data.len() / mem::size_of::<RawFd>())))
411             },
412             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => unsafe {
413                 Some(ControlMessage::ScmTimestamp(
414                     &*(cmsg_data.as_ptr() as *const _)))
415             },
416             (_, _) => unsafe {
417                 Some(ControlMessage::Unknown(UnknownCmsg(
418                     cmsg,
419                     slice::from_raw_parts(
420                         cmsg_data.as_ptr() as *const _,
421                         len))))
422             }
423         }
424     }
425 }
426 
427 /// A type-safe wrapper around a single control message. More types may
428 /// be added to this enum; do not exhaustively pattern-match it.
429 /// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
430 #[allow(missing_debug_implementations)]
431 pub enum ControlMessage<'a> {
432     /// A message of type `SCM_RIGHTS`, containing an array of file
433     /// descriptors passed between processes.
434     ///
435     /// See the description in the "Ancillary messages" section of the
436     /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
437     ScmRights(&'a [RawFd]),
438     /// A message of type `SCM_TIMESTAMP`, containing the time the
439     /// packet was received by the kernel.
440     ///
441     /// See the kernel's explanation in "SO_TIMESTAMP" of
442     /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
443     ///
444     /// # Examples
445     ///
446     // Disable this test on FreeBSD i386
447     // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
448     #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
449     #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
450     /// use nix::sys::socket::*;
451     /// use nix::sys::uio::IoVec;
452     /// use nix::sys::time::*;
453     /// use std::time::*;
454     ///
455     /// // Set up
456     /// let message1 = "Ohayō!".as_bytes();
457     /// let message2 = "Jā ne".as_bytes();
458     /// let in_socket = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
459     /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
460     /// bind(in_socket, &SockAddr::new_inet(InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0))).unwrap();
461     /// let address = if let Ok(address) = getsockname(in_socket) { address } else { unreachable!() };
462     ///
463     /// // Send both
464     /// assert!(Ok(message1.len()) == sendmsg(in_socket, &[IoVec::from_slice(message1)], &[], MsgFlags::empty(), Some(&address)));
465     /// let time = SystemTime::now();
466     /// std::thread::sleep(Duration::from_millis(250));
467     /// assert!(Ok(message2.len()) == sendmsg(in_socket, &[IoVec::from_slice(message2)], &[], MsgFlags::empty(), Some(&address)));
468     /// let delay = time.elapsed().unwrap();
469     ///
470     /// // Receive the first
471     /// let mut buffer1 = vec![0u8; message1.len() + message2.len()];
472     /// let mut time1: CmsgSpace<TimeVal> = CmsgSpace::new();
473     /// let received1 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer1)], Some(&mut time1), MsgFlags::empty()).unwrap();
474     /// let mut time1 = if let Some(ControlMessage::ScmTimestamp(&time1)) = received1.cmsgs().next() { time1 } else { panic!("Unexpected or no control message") };
475     ///
476     /// // Receive the second
477     /// let mut buffer2 = vec![0u8; message1.len() + message2.len()];
478     /// let mut time2: CmsgSpace<TimeVal> = CmsgSpace::new();
479     /// let received2 = recvmsg(in_socket, &[IoVec::from_mut_slice(&mut buffer2)], Some(&mut time2), MsgFlags::empty()).unwrap();
480     /// let mut time2 = if let Some(ControlMessage::ScmTimestamp(&time2)) = received2.cmsgs().next() { time2 } else { panic!("Unexpected or no control message") };
481     ///
482     /// // Swap if needed; UDP is unordered
483     /// match (received1.bytes, received2.bytes, message1.len(), message2.len()) {
484     ///     (l1, l2, m1, m2) if l1 == m1 && l2 == m2 => {},
485     ///     (l2, l1, m1, m2) if l1 == m1 && l2 == m2 => {
486     ///         std::mem::swap(&mut time1, &mut time2);
487     ///         std::mem::swap(&mut buffer1, &mut buffer2);
488     ///     },
489     ///     _ => panic!("Wrong packets"),
490     /// };
491     ///
492     /// // Compare results
493     /// println!("{:?} @ {:?}, {:?} @ {:?}, {:?}", buffer1, time1, buffer2, time2, delay);
494     /// assert!(message1 == &buffer1[0..(message1.len())], "{:?} == {:?}", message1, buffer1);
495     /// assert!(message2 == &buffer2[0..(message2.len())], "{:?} == {:?}", message2, buffer2);
496     /// let time = time2 - time1;
497     /// let time = Duration::new(time.num_seconds() as u64, time.num_nanoseconds() as u32);
498     /// let difference = if delay < time { time - delay } else { delay - time };
499     /// assert!(difference.subsec_nanos() < 5_000_000, "{}ns < 5ms", difference.subsec_nanos());
500     /// assert!(difference.as_secs() == 0);
501     ///
502     /// // Close socket
503     /// nix::unistd::close(in_socket).unwrap();
504     /// ```
505     ScmTimestamp(&'a TimeVal),
506     #[doc(hidden)]
507     Unknown(UnknownCmsg<'a>),
508 }
509 
510 // An opaque structure used to prevent cmsghdr from being a public type
511 #[doc(hidden)]
512 #[allow(missing_debug_implementations)]
513 pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
514 
515 // Round `len` up to meet the platform's required alignment for
516 // `cmsghdr`s and trailing `cmsghdr` data.  This should match the
517 // behaviour of CMSG_ALIGN from the Linux headers and do the correct
518 // thing on other platforms that don't usually provide CMSG_ALIGN.
519 #[inline]
cmsg_align(len: usize) -> usize520 fn cmsg_align(len: usize) -> usize {
521     let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
522     (len + align_bytes) & !align_bytes
523 }
524 
525 impl<'a> ControlMessage<'a> {
526     /// The value of CMSG_SPACE on this message.
space(&self) -> usize527     fn space(&self) -> usize {
528         cmsg_align(self.len())
529     }
530 
531     /// The value of CMSG_LEN on this message.
len(&self) -> usize532     fn len(&self) -> usize {
533         cmsg_align(mem::size_of::<cmsghdr>()) + match *self {
534             ControlMessage::ScmRights(fds) => {
535                 mem::size_of_val(fds)
536             },
537             ControlMessage::ScmTimestamp(t) => {
538                 mem::size_of_val(t)
539             },
540             ControlMessage::Unknown(UnknownCmsg(_, bytes)) => {
541                 mem::size_of_val(bytes)
542             }
543         }
544     }
545 
546     // Unsafe: start and end of buffer must be cmsg_align'd. Updates
547     // the provided slice; panics if the buffer is too small.
encode_into<'b>(&self, buf: &mut &'b mut [u8])548     unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
549         match *self {
550             ControlMessage::ScmRights(fds) => {
551                 let cmsg = cmsghdr {
552                     cmsg_len: self.len() as _,
553                     cmsg_level: libc::SOL_SOCKET,
554                     cmsg_type: libc::SCM_RIGHTS,
555                     ..mem::uninitialized()
556                 };
557                 copy_bytes(&cmsg, buf);
558 
559                 let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
560                     mem::size_of_val(&cmsg);
561 
562                 let mut tmpbuf = &mut [][..];
563                 mem::swap(&mut tmpbuf, buf);
564                 let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
565                 mem::swap(buf, &mut remainder);
566 
567                 copy_bytes(fds, buf);
568             },
569             ControlMessage::ScmTimestamp(t) => {
570                 let cmsg = cmsghdr {
571                     cmsg_len: self.len() as _,
572                     cmsg_level: libc::SOL_SOCKET,
573                     cmsg_type: libc::SCM_TIMESTAMP,
574                     ..mem::uninitialized()
575                 };
576                 copy_bytes(&cmsg, buf);
577 
578                 let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
579                     mem::size_of_val(&cmsg);
580 
581                 let mut tmpbuf = &mut [][..];
582                 mem::swap(&mut tmpbuf, buf);
583                 let (_padding, mut remainder) = tmpbuf.split_at_mut(padlen);
584                 mem::swap(buf, &mut remainder);
585 
586                 copy_bytes(t, buf);
587             },
588             ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
589                 copy_bytes(orig_cmsg, buf);
590                 copy_bytes(bytes, buf);
591             }
592         }
593     }
594 }
595 
596 
597 /// Send data in scatter-gather vectors to a socket, possibly accompanied
598 /// by ancillary data. Optionally direct the message at the given address,
599 /// as with sendto.
600 ///
601 /// Allocates if cmsgs is nonempty.
sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'a>], flags: MsgFlags, addr: Option<&'a SockAddr>) -> Result<usize>602 pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'a>], flags: MsgFlags, addr: Option<&'a SockAddr>) -> Result<usize> {
603     let mut len = 0;
604     let mut capacity = 0;
605     for cmsg in cmsgs {
606         len += cmsg.len();
607         capacity += cmsg.space();
608     }
609     // Note that the resulting vector claims to have length == capacity,
610     // so it's presently uninitialized.
611     let mut cmsg_buffer = unsafe {
612         let mut vec = Vec::<u8>::with_capacity(len);
613         vec.set_len(len);
614         vec
615     };
616     {
617         let mut ptr = &mut cmsg_buffer[..];
618         for cmsg in cmsgs {
619             unsafe { cmsg.encode_into(&mut ptr) };
620         }
621     }
622 
623     let (name, namelen) = match addr {
624         Some(addr) => { let (x, y) = unsafe { addr.as_ffi_pair() }; (x as *const _, y) }
625         None => (ptr::null(), 0),
626     };
627 
628     let cmsg_ptr = if capacity > 0 {
629         cmsg_buffer.as_ptr() as *const c_void
630     } else {
631         ptr::null()
632     };
633 
634     let mhdr = unsafe {
635         let mut mhdr: msghdr = mem::uninitialized();
636         mhdr.msg_name =  name as *mut _;
637         mhdr.msg_namelen =  namelen;
638         mhdr.msg_iov =  iov.as_ptr() as *mut _;
639         mhdr.msg_iovlen =  iov.len() as _;
640         mhdr.msg_control =  cmsg_ptr as *mut _;
641         mhdr.msg_controllen =  capacity as _;
642         mhdr.msg_flags =  0;
643         mhdr
644     };
645     let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
646 
647     Errno::result(ret).map(|r| r as usize)
648 }
649 
650 /// Receive message in scatter-gather vectors from a socket, and
651 /// optionally receive ancillary data into the provided buffer.
652 /// 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>>653 pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&'a mut CmsgSpace<T>>, flags: MsgFlags) -> Result<RecvMsg<'a>> {
654     let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
655     let (msg_control, msg_controllen) = match cmsg_buffer {
656         Some(cmsg_buffer) => (cmsg_buffer as *mut _, mem::size_of_val(cmsg_buffer)),
657         None => (ptr::null_mut(), 0),
658     };
659     let mut mhdr = unsafe {
660         let mut mhdr: msghdr = mem::uninitialized();
661         mhdr.msg_name =  &mut address as *mut _ as *mut _;
662         mhdr.msg_namelen =  mem::size_of::<sockaddr_storage>() as socklen_t;
663         mhdr.msg_iov =  iov.as_ptr() as *mut _;
664         mhdr.msg_iovlen =  iov.len() as _;
665         mhdr.msg_control =  msg_control as *mut _;
666         mhdr.msg_controllen =  msg_controllen as _;
667         mhdr.msg_flags =  0;
668         mhdr
669     };
670     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
671 
672     Ok(unsafe { RecvMsg {
673         bytes: try!(Errno::result(ret)) as usize,
674         cmsg_buffer: slice::from_raw_parts(mhdr.msg_control as *const u8,
675                                            mhdr.msg_controllen as usize),
676         address: sockaddr_storage_to_addr(&address,
677                                           mhdr.msg_namelen as usize).ok(),
678         flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
679     } })
680 }
681 
682 
683 /// Create an endpoint for communication
684 ///
685 /// The `protocol` specifies a particular protocol to be used with the
686 /// socket.  Normally only a single protocol exists to support a
687 /// particular socket type within a given protocol family, in which case
688 /// protocol can be specified as `None`.  However, it is possible that many
689 /// protocols may exist, in which case a particular protocol must be
690 /// specified in this manner.
691 ///
692 /// [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>693 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
694     let protocol = match protocol.into() {
695         None => 0,
696         Some(p) => p as c_int,
697     };
698 
699     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
700     // little easier to understand by separating it out. So we have to merge these bitfields
701     // here.
702     let mut ty = ty as c_int;
703     ty |= flags.bits();
704 
705     let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
706 
707     Errno::result(res)
708 }
709 
710 /// Create a pair of connected sockets
711 ///
712 /// [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)>713 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
714                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
715     let protocol = match protocol.into() {
716         None => 0,
717         Some(p) => p as c_int,
718     };
719 
720     // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
721     // little easier to understand by separating it out. So we have to merge these bitfields
722     // here.
723     let mut ty = ty as c_int;
724     ty |= flags.bits();
725 
726     let mut fds = [-1, -1];
727 
728     let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
729     Errno::result(res)?;
730 
731     Ok((fds[0], fds[1]))
732 }
733 
734 /// Listen for connections on a socket
735 ///
736 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
listen(sockfd: RawFd, backlog: usize) -> Result<()>737 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
738     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
739 
740     Errno::result(res).map(drop)
741 }
742 
743 /// Bind a name to a socket
744 ///
745 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
bind(fd: RawFd, addr: &SockAddr) -> Result<()>746 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
747     let res = unsafe {
748         let (ptr, len) = addr.as_ffi_pair();
749         libc::bind(fd, ptr, len)
750     };
751 
752     Errno::result(res).map(drop)
753 }
754 
755 /// Accept a connection on a socket
756 ///
757 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
accept(sockfd: RawFd) -> Result<RawFd>758 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
759     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
760 
761     Errno::result(res)
762 }
763 
764 /// Accept a connection on a socket
765 ///
766 /// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
767 #[cfg(any(target_os = "android",
768           target_os = "freebsd",
769           target_os = "linux",
770           target_os = "openbsd"))]
accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd>771 pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
772     let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
773 
774     Errno::result(res)
775 }
776 
777 /// Initiate a connection on a socket
778 ///
779 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
connect(fd: RawFd, addr: &SockAddr) -> Result<()>780 pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
781     let res = unsafe {
782         let (ptr, len) = addr.as_ffi_pair();
783         libc::connect(fd, ptr, len)
784     };
785 
786     Errno::result(res).map(drop)
787 }
788 
789 /// Receive data from a connection-oriented socket. Returns the number of
790 /// bytes read
791 ///
792 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize>793 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
794     unsafe {
795         let ret = libc::recv(
796             sockfd,
797             buf.as_ptr() as *mut c_void,
798             buf.len() as size_t,
799             flags.bits());
800 
801         Errno::result(ret).map(|r| r as usize)
802     }
803 }
804 
805 /// Receive data from a connectionless or connection-oriented socket. Returns
806 /// the number of bytes read and the socket address of the sender.
807 ///
808 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)>809 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
810     unsafe {
811         let addr: sockaddr_storage = mem::zeroed();
812         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
813 
814         let ret = try!(Errno::result(libc::recvfrom(
815             sockfd,
816             buf.as_ptr() as *mut c_void,
817             buf.len() as size_t,
818             0,
819             mem::transmute(&addr),
820             &mut len as *mut socklen_t)));
821 
822         sockaddr_storage_to_addr(&addr, len as usize)
823             .map(|addr| (ret as usize, addr))
824     }
825 }
826 
827 /// Send a message to a socket
828 ///
829 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize>830 pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
831     let ret = unsafe {
832         let (ptr, len) = addr.as_ffi_pair();
833         libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
834     };
835 
836     Errno::result(ret).map(|r| r as usize)
837 }
838 
839 /// Send data to a connection-oriented socket. Returns the number of bytes read
840 ///
841 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize>842 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
843     let ret = unsafe {
844         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
845     };
846 
847     Errno::result(ret).map(|r| r as usize)
848 }
849 
850 /*
851  *
852  * ===== Socket Options =====
853  *
854  */
855 
856 /// The protocol level at which to get / set socket options. Used as an
857 /// argument to `getsockopt` and `setsockopt`.
858 ///
859 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
860 #[repr(i32)]
861 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
862 pub enum SockLevel {
863     Socket = libc::SOL_SOCKET,
864     Tcp = libc::IPPROTO_TCP,
865     Ip = libc::IPPROTO_IP,
866     Ipv6 = libc::IPPROTO_IPV6,
867     Udp = libc::IPPROTO_UDP,
868     #[cfg(any(target_os = "android", target_os = "linux"))]
869     Netlink = libc::SOL_NETLINK,
870 }
871 
872 /// Represents a socket option that can be accessed or set. Used as an argument
873 /// to `getsockopt`
874 pub trait GetSockOpt : Copy {
875     type Val;
876 
877     #[doc(hidden)]
get(&self, fd: RawFd) -> Result<Self::Val>878     fn get(&self, fd: RawFd) -> Result<Self::Val>;
879 }
880 
881 /// Represents a socket option that can be accessed or set. Used as an argument
882 /// to `setsockopt`
883 pub trait SetSockOpt : Copy {
884     type Val;
885 
886     #[doc(hidden)]
set(&self, fd: RawFd, val: &Self::Val) -> Result<()>887     fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
888 }
889 
890 /// Get the current value for the requested socket option
891 ///
892 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val>893 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
894     opt.get(fd)
895 }
896 
897 /// Sets the value for the requested socket option
898 ///
899 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>900 pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
901     opt.set(fd, val)
902 }
903 
904 /// Get the address of the peer connected to the socket `fd`.
905 ///
906 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
getpeername(fd: RawFd) -> Result<SockAddr>907 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
908     unsafe {
909         let addr: sockaddr_storage = mem::uninitialized();
910         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
911 
912         let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
913 
914         try!(Errno::result(ret));
915 
916         sockaddr_storage_to_addr(&addr, len as usize)
917     }
918 }
919 
920 /// Get the current address to which the socket `fd` is bound.
921 ///
922 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
getsockname(fd: RawFd) -> Result<SockAddr>923 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
924     unsafe {
925         let addr: sockaddr_storage = mem::uninitialized();
926         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
927 
928         let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
929 
930         try!(Errno::result(ret));
931 
932         sockaddr_storage_to_addr(&addr, len as usize)
933     }
934 }
935 
936 /// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
937 /// size.  In C this would usually be done by casting.  The `len` argument
938 /// should be the number of bytes in the `sockaddr_storage` that are actually
939 /// allocated and valid.  It must be at least as large as all the useful parts
940 /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
941 /// include the terminating null.
sockaddr_storage_to_addr( addr: &sockaddr_storage, len: usize) -> Result<SockAddr>942 pub unsafe fn sockaddr_storage_to_addr(
943     addr: &sockaddr_storage,
944     len: usize) -> Result<SockAddr> {
945 
946     if len < mem::size_of_val(&addr.ss_family) {
947         return Err(Error::Sys(Errno::ENOTCONN));
948     }
949 
950     match addr.ss_family as c_int {
951         libc::AF_INET => {
952             assert!(len as usize == mem::size_of::<sockaddr_in>());
953             let ret = *(addr as *const _ as *const sockaddr_in);
954             Ok(SockAddr::Inet(InetAddr::V4(ret)))
955         }
956         libc::AF_INET6 => {
957             assert!(len as usize == mem::size_of::<sockaddr_in6>());
958             Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
959         }
960         libc::AF_UNIX => {
961             let sun = *(addr as *const _ as *const sockaddr_un);
962             let pathlen = len - offset_of!(sockaddr_un, sun_path);
963             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
964         }
965         #[cfg(any(target_os = "linux", target_os = "android"))]
966         libc::AF_NETLINK => {
967             use libc::sockaddr_nl;
968             Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
969         }
970         af => panic!("unexpected address family {}", af),
971     }
972 }
973 
974 
975 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
976 pub enum Shutdown {
977     /// Further receptions will be disallowed.
978     Read,
979     /// Further  transmissions will be disallowed.
980     Write,
981     /// Further receptions and transmissions will be disallowed.
982     Both,
983 }
984 
985 /// Shut down part of a full-duplex connection.
986 ///
987 /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
shutdown(df: RawFd, how: Shutdown) -> Result<()>988 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
989     unsafe {
990         use libc::shutdown;
991 
992         let how = match how {
993             Shutdown::Read  => libc::SHUT_RD,
994             Shutdown::Write => libc::SHUT_WR,
995             Shutdown::Both  => libc::SHUT_RDWR,
996         };
997 
998         Errno::result(shutdown(df, how)).map(drop)
999     }
1000 }
1001