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