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