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