1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 use std::cmp;
12 use std::fmt;
13 use std::io;
14 use std::io::{ErrorKind, Read, Write};
15 use std::mem;
16 use std::net::Shutdown;
17 use std::net::{self, Ipv4Addr, Ipv6Addr};
18 use std::ops::Neg;
19 #[cfg(feature = "unix")]
20 use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
21 use std::os::unix::prelude::*;
22 use std::sync::atomic::{AtomicBool, Ordering};
23 use std::time::{Duration, Instant};
24 
25 use libc::{self, c_void, socklen_t, ssize_t};
26 
27 use crate::{Domain, Type};
28 
29 pub use libc::c_int;
30 
31 // Used in `Domain`.
32 pub(crate) use libc::{AF_INET, AF_INET6};
33 // Used in `Type`.
34 pub(crate) use libc::{SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM};
35 // Used in `Protocol`.
36 pub(crate) use libc::{IPPROTO_ICMP, IPPROTO_ICMPV6, IPPROTO_TCP, IPPROTO_UDP};
37 
38 cfg_if::cfg_if! {
39     if #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
40                  target_os = "ios", target_os = "macos",
41                  target_os = "openbsd", target_os = "netbsd",
42                  target_os = "solaris", target_os = "illumos",
43                  target_os = "haiku"))] {
44         use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
45         use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
46     } else {
47         use libc::IPV6_ADD_MEMBERSHIP;
48         use libc::IPV6_DROP_MEMBERSHIP;
49     }
50 }
51 
52 cfg_if::cfg_if! {
53     if #[cfg(any(target_os = "macos", target_os = "ios"))] {
54         use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
55     } else if #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "haiku"))] {
56         use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
57     } else {
58         use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
59     }
60 }
61 
62 use crate::utils::One;
63 use crate::SockAddr;
64 
65 /// Unix only API.
66 impl Domain {
67     /// Domain for Unix socket communication, corresponding to `AF_UNIX`.
unix() -> Domain68     pub fn unix() -> Domain {
69         Domain(libc::AF_UNIX)
70     }
71 
72     /// Domain for low-level packet interface, corresponding to `AF_PACKET`.
73     ///
74     /// # Notes
75     ///
76     /// This function is only available on Linux.
77     #[cfg(target_os = "linux")]
packet() -> Domain78     pub fn packet() -> Domain {
79         Domain(libc::AF_PACKET)
80     }
81 }
82 
83 impl_debug!(
84     Domain,
85     libc::AF_INET,
86     libc::AF_INET6,
87     libc::AF_UNIX,
88     libc::AF_UNSPEC, // = 0.
89 );
90 
91 /// Unix only API.
92 impl Type {
93     /// Set `SOCK_NONBLOCK` on the `Type`.
94     ///
95     /// # Notes
96     ///
97     /// This function is only available on Android, DragonFlyBSD, FreeBSD,
98     /// Linux, NetBSD and OpenBSD.
99     #[cfg(any(
100         target_os = "android",
101         target_os = "dragonfly",
102         target_os = "freebsd",
103         target_os = "linux",
104         target_os = "netbsd",
105         target_os = "openbsd"
106     ))]
non_blocking(self) -> Type107     pub fn non_blocking(self) -> Type {
108         Type(self.0 | libc::SOCK_NONBLOCK)
109     }
110 
111     /// Set `SOCK_CLOEXEC` on the `Type`.
112     ///
113     /// # Notes
114     ///
115     /// This function is only available on Android, DragonFlyBSD, FreeBSD,
116     /// Linux, NetBSD and OpenBSD.
117     #[cfg(any(
118         target_os = "android",
119         target_os = "dragonfly",
120         target_os = "freebsd",
121         target_os = "linux",
122         target_os = "netbsd",
123         target_os = "openbsd"
124     ))]
cloexec(self) -> Type125     pub fn cloexec(self) -> Type {
126         Type(self.0 | libc::SOCK_CLOEXEC)
127     }
128 }
129 
130 impl_debug!(
131     crate::Type,
132     libc::SOCK_STREAM,
133     libc::SOCK_DGRAM,
134     libc::SOCK_RAW,
135     libc::SOCK_RDM,
136     libc::SOCK_SEQPACKET,
137     /* TODO: add these optional bit OR-ed flags:
138     #[cfg(any(
139         target_os = "android",
140         target_os = "dragonfly",
141         target_os = "freebsd",
142         target_os = "linux",
143         target_os = "netbsd",
144         target_os = "openbsd"
145     ))]
146     libc::SOCK_NONBLOCK,
147     #[cfg(any(
148         target_os = "android",
149         target_os = "dragonfly",
150         target_os = "freebsd",
151         target_os = "linux",
152         target_os = "netbsd",
153         target_os = "openbsd"
154     ))]
155     libc::SOCK_CLOEXEC,
156     */
157 );
158 
159 impl_debug!(
160     crate::Protocol,
161     libc::IPPROTO_ICMP,
162     libc::IPPROTO_ICMPV6,
163     libc::IPPROTO_TCP,
164     libc::IPPROTO_UDP,
165 );
166 
167 pub struct Socket {
168     fd: c_int,
169 }
170 
171 impl Socket {
new(family: c_int, ty: c_int, protocol: c_int) -> io::Result<Socket>172     pub fn new(family: c_int, ty: c_int, protocol: c_int) -> io::Result<Socket> {
173         unsafe {
174             // On linux we first attempt to pass the SOCK_CLOEXEC flag to
175             // atomically create the socket and set it as CLOEXEC. Support for
176             // this option, however, was added in 2.6.27, and we still support
177             // 2.6.18 as a kernel, so if the returned error is EINVAL we
178             // fallthrough to the fallback.
179             #[cfg(target_os = "linux")]
180             {
181                 match cvt(libc::socket(family, ty | libc::SOCK_CLOEXEC, protocol)) {
182                     Ok(fd) => return Ok(Socket::from_raw_fd(fd)),
183                     Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
184                     Err(e) => return Err(e),
185                 }
186             }
187 
188             let fd = cvt(libc::socket(family, ty, protocol))?;
189             let fd = Socket::from_raw_fd(fd);
190             set_cloexec(fd.as_raw_fd())?;
191             #[cfg(target_os = "macos")]
192             {
193                 fd.setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
194             }
195             Ok(fd)
196         }
197     }
198 
pair(family: c_int, ty: c_int, protocol: c_int) -> io::Result<(Socket, Socket)>199     pub fn pair(family: c_int, ty: c_int, protocol: c_int) -> io::Result<(Socket, Socket)> {
200         unsafe {
201             let mut fds = [0, 0];
202             cvt(libc::socketpair(family, ty, protocol, fds.as_mut_ptr()))?;
203             let fds = (Socket::from_raw_fd(fds[0]), Socket::from_raw_fd(fds[1]));
204             set_cloexec(fds.0.as_raw_fd())?;
205             set_cloexec(fds.1.as_raw_fd())?;
206             #[cfg(target_os = "macos")]
207             {
208                 fds.0
209                     .setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
210                 fds.1
211                     .setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
212             }
213             Ok(fds)
214         }
215     }
216 
bind(&self, addr: &SockAddr) -> io::Result<()>217     pub fn bind(&self, addr: &SockAddr) -> io::Result<()> {
218         unsafe { cvt(libc::bind(self.fd, addr.as_ptr(), addr.len() as _)).map(|_| ()) }
219     }
220 
listen(&self, backlog: i32) -> io::Result<()>221     pub fn listen(&self, backlog: i32) -> io::Result<()> {
222         unsafe { cvt(libc::listen(self.fd, backlog)).map(|_| ()) }
223     }
224 
connect(&self, addr: &SockAddr) -> io::Result<()>225     pub fn connect(&self, addr: &SockAddr) -> io::Result<()> {
226         unsafe { cvt(libc::connect(self.fd, addr.as_ptr(), addr.len())).map(|_| ()) }
227     }
228 
connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()>229     pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
230         self.set_nonblocking(true)?;
231         let r = self.connect(addr);
232         self.set_nonblocking(false)?;
233 
234         match r {
235             Ok(()) => return Ok(()),
236             // there's no io::ErrorKind conversion registered for EINPROGRESS :(
237             Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
238             Err(e) => return Err(e),
239         }
240 
241         let mut pollfd = libc::pollfd {
242             fd: self.fd,
243             events: libc::POLLOUT,
244             revents: 0,
245         };
246 
247         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
248             return Err(io::Error::new(
249                 io::ErrorKind::InvalidInput,
250                 "cannot set a 0 duration timeout",
251             ));
252         }
253 
254         let start = Instant::now();
255 
256         loop {
257             let elapsed = start.elapsed();
258             if elapsed >= timeout {
259                 return Err(io::Error::new(
260                     io::ErrorKind::TimedOut,
261                     "connection timed out",
262                 ));
263             }
264 
265             let timeout = timeout - elapsed;
266             let mut timeout = timeout
267                 .as_secs()
268                 .saturating_mul(1_000)
269                 .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
270             if timeout == 0 {
271                 timeout = 1;
272             }
273 
274             let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
275 
276             match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
277                 -1 => {
278                     let err = io::Error::last_os_error();
279                     if err.kind() != io::ErrorKind::Interrupted {
280                         return Err(err);
281                     }
282                 }
283                 0 => {
284                     return Err(io::Error::new(
285                         io::ErrorKind::TimedOut,
286                         "connection timed out",
287                     ))
288                 }
289                 _ => {
290                     // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
291                     // for POLLHUP rather than read readiness
292                     if pollfd.revents & libc::POLLHUP != 0 {
293                         let e = self.take_error()?.unwrap_or_else(|| {
294                             io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
295                         });
296                         return Err(e);
297                     }
298                     return Ok(());
299                 }
300             }
301         }
302     }
303 
local_addr(&self) -> io::Result<SockAddr>304     pub fn local_addr(&self) -> io::Result<SockAddr> {
305         unsafe {
306             let mut storage: libc::sockaddr_storage = mem::zeroed();
307             let mut len = mem::size_of_val(&storage) as libc::socklen_t;
308             cvt(libc::getsockname(
309                 self.fd,
310                 &mut storage as *mut _ as *mut _,
311                 &mut len,
312             ))?;
313             Ok(SockAddr::from_raw_parts(
314                 &storage as *const _ as *const _,
315                 len,
316             ))
317         }
318     }
319 
peer_addr(&self) -> io::Result<SockAddr>320     pub fn peer_addr(&self) -> io::Result<SockAddr> {
321         unsafe {
322             let mut storage: libc::sockaddr_storage = mem::zeroed();
323             let mut len = mem::size_of_val(&storage) as libc::socklen_t;
324             cvt(libc::getpeername(
325                 self.fd,
326                 &mut storage as *mut _ as *mut _,
327                 &mut len,
328             ))?;
329             Ok(SockAddr::from_raw_parts(
330                 &storage as *const _ as *const _,
331                 len,
332             ))
333         }
334     }
335 
try_clone(&self) -> io::Result<Socket>336     pub fn try_clone(&self) -> io::Result<Socket> {
337         // implementation lifted from libstd
338         #[cfg(any(target_os = "android", target_os = "haiku"))]
339         use libc::F_DUPFD as F_DUPFD_CLOEXEC;
340         #[cfg(not(any(target_os = "android", target_os = "haiku")))]
341         use libc::F_DUPFD_CLOEXEC;
342 
343         static CLOEXEC_FAILED: AtomicBool = AtomicBool::new(false);
344         unsafe {
345             if !CLOEXEC_FAILED.load(Ordering::Relaxed) {
346                 match cvt(libc::fcntl(self.fd, F_DUPFD_CLOEXEC, 0)) {
347                     Ok(fd) => {
348                         let fd = Socket::from_raw_fd(fd);
349                         if cfg!(target_os = "linux") {
350                             set_cloexec(fd.as_raw_fd())?;
351                         }
352                         return Ok(fd);
353                     }
354                     Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {
355                         CLOEXEC_FAILED.store(true, Ordering::Relaxed);
356                     }
357                     Err(e) => return Err(e),
358                 }
359             }
360             let fd = cvt(libc::fcntl(self.fd, libc::F_DUPFD, 0))?;
361             let fd = Socket::from_raw_fd(fd);
362             set_cloexec(fd.as_raw_fd())?;
363             Ok(fd)
364         }
365     }
366 
367     #[allow(unused_mut)]
accept(&self) -> io::Result<(Socket, SockAddr)>368     pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
369         let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
370         let mut len = mem::size_of_val(&storage) as socklen_t;
371 
372         let mut socket = None;
373         #[cfg(target_os = "linux")]
374         {
375             let res = cvt_r(|| unsafe {
376                 libc::syscall(
377                     libc::SYS_accept4,
378                     self.fd as libc::c_long,
379                     &mut storage as *mut _ as libc::c_long,
380                     &mut len,
381                     libc::SOCK_CLOEXEC as libc::c_long,
382                 ) as libc::c_int
383             });
384             match res {
385                 Ok(fd) => socket = Some(Socket { fd: fd }),
386                 Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
387                 Err(e) => return Err(e),
388             }
389         }
390 
391         let socket = match socket {
392             Some(socket) => socket,
393             None => unsafe {
394                 let fd =
395                     cvt_r(|| libc::accept(self.fd, &mut storage as *mut _ as *mut _, &mut len))?;
396                 let fd = Socket::from_raw_fd(fd);
397                 set_cloexec(fd.as_raw_fd())?;
398                 fd
399             },
400         };
401         let addr = unsafe { SockAddr::from_raw_parts(&storage as *const _ as *const _, len) };
402         Ok((socket, addr))
403     }
404 
take_error(&self) -> io::Result<Option<io::Error>>405     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
406         unsafe {
407             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_ERROR)?;
408             if raw == 0 {
409                 Ok(None)
410             } else {
411                 Ok(Some(io::Error::from_raw_os_error(raw as i32)))
412             }
413         }
414     }
415 
set_nonblocking(&self, nonblocking: bool) -> io::Result<()>416     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
417         unsafe {
418             let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
419             let new = if nonblocking {
420                 previous | libc::O_NONBLOCK
421             } else {
422                 previous & !libc::O_NONBLOCK
423             };
424             if new != previous {
425                 cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
426             }
427             Ok(())
428         }
429     }
430 
shutdown(&self, how: Shutdown) -> io::Result<()>431     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
432         let how = match how {
433             Shutdown::Write => libc::SHUT_WR,
434             Shutdown::Read => libc::SHUT_RD,
435             Shutdown::Both => libc::SHUT_RDWR,
436         };
437         cvt(unsafe { libc::shutdown(self.fd, how) })?;
438         Ok(())
439     }
440 
recv(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize>441     pub fn recv(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
442         unsafe {
443             let n = cvt({
444                 libc::recv(
445                     self.fd,
446                     buf.as_mut_ptr() as *mut c_void,
447                     cmp::min(buf.len(), max_len()),
448                     flags,
449                 )
450             })?;
451             Ok(n as usize)
452         }
453     }
454 
peek(&self, buf: &mut [u8]) -> io::Result<usize>455     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
456         unsafe {
457             let n = cvt({
458                 libc::recv(
459                     self.fd,
460                     buf.as_mut_ptr() as *mut c_void,
461                     cmp::min(buf.len(), max_len()),
462                     libc::MSG_PEEK,
463                 )
464             })?;
465             Ok(n as usize)
466         }
467     }
468 
peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)>469     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
470         self.recv_from(buf, libc::MSG_PEEK)
471     }
472 
recv_from(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, SockAddr)>473     pub fn recv_from(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, SockAddr)> {
474         unsafe {
475             let mut storage: libc::sockaddr_storage = mem::zeroed();
476             let mut addrlen = mem::size_of_val(&storage) as socklen_t;
477 
478             let n = cvt({
479                 libc::recvfrom(
480                     self.fd,
481                     buf.as_mut_ptr() as *mut c_void,
482                     cmp::min(buf.len(), max_len()),
483                     flags,
484                     &mut storage as *mut _ as *mut _,
485                     &mut addrlen,
486                 )
487             })?;
488             let addr = SockAddr::from_raw_parts(&storage as *const _ as *const _, addrlen);
489             Ok((n as usize, addr))
490         }
491     }
492 
send(&self, buf: &[u8], flags: c_int) -> io::Result<usize>493     pub fn send(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
494         unsafe {
495             let n = cvt({
496                 libc::send(
497                     self.fd,
498                     buf.as_ptr() as *const c_void,
499                     cmp::min(buf.len(), max_len()),
500                     flags,
501                 )
502             })?;
503             Ok(n as usize)
504         }
505     }
506 
send_to(&self, buf: &[u8], flags: c_int, addr: &SockAddr) -> io::Result<usize>507     pub fn send_to(&self, buf: &[u8], flags: c_int, addr: &SockAddr) -> io::Result<usize> {
508         unsafe {
509             let n = cvt({
510                 libc::sendto(
511                     self.fd,
512                     buf.as_ptr() as *const c_void,
513                     cmp::min(buf.len(), max_len()),
514                     flags,
515                     addr.as_ptr(),
516                     addr.len(),
517                 )
518             })?;
519             Ok(n as usize)
520         }
521     }
522 
523     // ================================================
524 
ttl(&self) -> io::Result<u32>525     pub fn ttl(&self) -> io::Result<u32> {
526         unsafe {
527             let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_TTL)?;
528             Ok(raw as u32)
529         }
530     }
531 
set_ttl(&self, ttl: u32) -> io::Result<()>532     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
533         unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_TTL, ttl as c_int) }
534     }
535 
unicast_hops_v6(&self) -> io::Result<u32>536     pub fn unicast_hops_v6(&self) -> io::Result<u32> {
537         unsafe {
538             let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_UNICAST_HOPS)?;
539             Ok(raw as u32)
540         }
541     }
542 
set_unicast_hops_v6(&self, hops: u32) -> io::Result<()>543     pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> {
544         unsafe {
545             self.setsockopt(
546                 libc::IPPROTO_IPV6 as c_int,
547                 libc::IPV6_UNICAST_HOPS,
548                 hops as c_int,
549             )
550         }
551     }
552 
only_v6(&self) -> io::Result<bool>553     pub fn only_v6(&self) -> io::Result<bool> {
554         unsafe {
555             let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_V6ONLY)?;
556             Ok(raw != 0)
557         }
558     }
559 
set_only_v6(&self, only_v6: bool) -> io::Result<()>560     pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
561         unsafe { self.setsockopt(libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, only_v6 as c_int) }
562     }
563 
read_timeout(&self) -> io::Result<Option<Duration>>564     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
565         unsafe {
566             Ok(timeval2dur(
567                 self.getsockopt(libc::SOL_SOCKET, libc::SO_RCVTIMEO)?,
568             ))
569         }
570     }
571 
set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>572     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
573         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_RCVTIMEO, dur2timeval(dur)?) }
574     }
575 
write_timeout(&self) -> io::Result<Option<Duration>>576     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
577         unsafe {
578             Ok(timeval2dur(
579                 self.getsockopt(libc::SOL_SOCKET, libc::SO_SNDTIMEO)?,
580             ))
581         }
582     }
583 
set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>584     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
585         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_SNDTIMEO, dur2timeval(dur)?) }
586     }
587 
nodelay(&self) -> io::Result<bool>588     pub fn nodelay(&self) -> io::Result<bool> {
589         unsafe {
590             let raw: c_int = self.getsockopt(libc::IPPROTO_TCP, libc::TCP_NODELAY)?;
591             Ok(raw != 0)
592         }
593     }
594 
set_nodelay(&self, nodelay: bool) -> io::Result<()>595     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
596         unsafe { self.setsockopt(libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int) }
597     }
598 
broadcast(&self) -> io::Result<bool>599     pub fn broadcast(&self) -> io::Result<bool> {
600         unsafe {
601             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_BROADCAST)?;
602             Ok(raw != 0)
603         }
604     }
605 
set_broadcast(&self, broadcast: bool) -> io::Result<()>606     pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
607         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_BROADCAST, broadcast as c_int) }
608     }
609 
multicast_loop_v4(&self) -> io::Result<bool>610     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
611         unsafe {
612             let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP)?;
613             Ok(raw != 0)
614         }
615     }
616 
set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>617     pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
618         unsafe {
619             self.setsockopt(
620                 libc::IPPROTO_IP,
621                 libc::IP_MULTICAST_LOOP,
622                 multicast_loop_v4 as c_int,
623             )
624         }
625     }
626 
multicast_ttl_v4(&self) -> io::Result<u32>627     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
628         unsafe {
629             let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_TTL)?;
630             Ok(raw as u32)
631         }
632     }
633 
set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>634     pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
635         unsafe {
636             self.setsockopt(
637                 libc::IPPROTO_IP,
638                 libc::IP_MULTICAST_TTL,
639                 multicast_ttl_v4 as c_int,
640             )
641         }
642     }
643 
multicast_hops_v6(&self) -> io::Result<u32>644     pub fn multicast_hops_v6(&self) -> io::Result<u32> {
645         unsafe {
646             let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_HOPS)?;
647             Ok(raw as u32)
648         }
649     }
650 
set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>651     pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
652         unsafe { self.setsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_HOPS, hops as c_int) }
653     }
654 
multicast_if_v4(&self) -> io::Result<Ipv4Addr>655     pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
656         unsafe {
657             let imr_interface: libc::in_addr =
658                 self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_IF)?;
659             Ok(from_s_addr(imr_interface.s_addr))
660         }
661     }
662 
set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>663     pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> {
664         let interface = to_s_addr(interface);
665         let imr_interface = libc::in_addr { s_addr: interface };
666 
667         unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_IF, imr_interface) }
668     }
669 
multicast_if_v6(&self) -> io::Result<u32>670     pub fn multicast_if_v6(&self) -> io::Result<u32> {
671         unsafe {
672             let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_IF)?;
673             Ok(raw as u32)
674         }
675     }
676 
set_multicast_if_v6(&self, interface: u32) -> io::Result<()>677     pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
678         unsafe {
679             self.setsockopt(
680                 libc::IPPROTO_IPV6,
681                 libc::IPV6_MULTICAST_IF,
682                 interface as c_int,
683             )
684         }
685     }
686 
multicast_loop_v6(&self) -> io::Result<bool>687     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
688         unsafe {
689             let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_LOOP)?;
690             Ok(raw != 0)
691         }
692     }
693 
set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>694     pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
695         unsafe {
696             self.setsockopt(
697                 libc::IPPROTO_IPV6,
698                 libc::IPV6_MULTICAST_LOOP,
699                 multicast_loop_v6 as c_int,
700             )
701         }
702     }
703 
join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>704     pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
705         let multiaddr = to_s_addr(multiaddr);
706         let interface = to_s_addr(interface);
707         let mreq = libc::ip_mreq {
708             imr_multiaddr: libc::in_addr { s_addr: multiaddr },
709             imr_interface: libc::in_addr { s_addr: interface },
710         };
711         unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, mreq) }
712     }
713 
join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>714     pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
715         let multiaddr = to_in6_addr(multiaddr);
716         let mreq = libc::ipv6_mreq {
717             ipv6mr_multiaddr: multiaddr,
718             ipv6mr_interface: to_ipv6mr_interface(interface),
719         };
720         unsafe { self.setsockopt(libc::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
721     }
722 
leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>723     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
724         let multiaddr = to_s_addr(multiaddr);
725         let interface = to_s_addr(interface);
726         let mreq = libc::ip_mreq {
727             imr_multiaddr: libc::in_addr { s_addr: multiaddr },
728             imr_interface: libc::in_addr { s_addr: interface },
729         };
730         unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, mreq) }
731     }
732 
leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>733     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
734         let multiaddr = to_in6_addr(multiaddr);
735         let mreq = libc::ipv6_mreq {
736             ipv6mr_multiaddr: multiaddr,
737             ipv6mr_interface: to_ipv6mr_interface(interface),
738         };
739         unsafe { self.setsockopt(libc::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
740     }
741 
linger(&self) -> io::Result<Option<Duration>>742     pub fn linger(&self) -> io::Result<Option<Duration>> {
743         unsafe {
744             Ok(linger2dur(
745                 self.getsockopt(libc::SOL_SOCKET, libc::SO_LINGER)?,
746             ))
747         }
748     }
749 
set_linger(&self, dur: Option<Duration>) -> io::Result<()>750     pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
751         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_LINGER, dur2linger(dur)) }
752     }
753 
set_reuse_address(&self, reuse: bool) -> io::Result<()>754     pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
755         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_REUSEADDR, reuse as c_int) }
756     }
757 
reuse_address(&self) -> io::Result<bool>758     pub fn reuse_address(&self) -> io::Result<bool> {
759         unsafe {
760             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_REUSEADDR)?;
761             Ok(raw != 0)
762         }
763     }
764 
recv_buffer_size(&self) -> io::Result<usize>765     pub fn recv_buffer_size(&self) -> io::Result<usize> {
766         unsafe {
767             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_RCVBUF)?;
768             Ok(raw as usize)
769         }
770     }
771 
set_recv_buffer_size(&self, size: usize) -> io::Result<()>772     pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
773         unsafe {
774             // TODO: casting usize to a c_int should be a checked cast
775             self.setsockopt(libc::SOL_SOCKET, libc::SO_RCVBUF, size as c_int)
776         }
777     }
778 
send_buffer_size(&self) -> io::Result<usize>779     pub fn send_buffer_size(&self) -> io::Result<usize> {
780         unsafe {
781             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_SNDBUF)?;
782             Ok(raw as usize)
783         }
784     }
785 
set_send_buffer_size(&self, size: usize) -> io::Result<()>786     pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
787         unsafe {
788             // TODO: casting usize to a c_int should be a checked cast
789             self.setsockopt(libc::SOL_SOCKET, libc::SO_SNDBUF, size as c_int)
790         }
791     }
792 
keepalive(&self) -> io::Result<Option<Duration>>793     pub fn keepalive(&self) -> io::Result<Option<Duration>> {
794         unsafe {
795             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_KEEPALIVE)?;
796             if raw == 0 {
797                 return Ok(None);
798             }
799             let secs: c_int = self.getsockopt(libc::IPPROTO_TCP, KEEPALIVE_OPTION)?;
800             Ok(Some(Duration::new(secs as u64, 0)))
801         }
802     }
803 
set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()>804     pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
805         unsafe {
806             self.setsockopt(
807                 libc::SOL_SOCKET,
808                 libc::SO_KEEPALIVE,
809                 keepalive.is_some() as c_int,
810             )?;
811             if let Some(dur) = keepalive {
812                 // TODO: checked cast here
813                 self.setsockopt(libc::IPPROTO_TCP, KEEPALIVE_OPTION, dur.as_secs() as c_int)?;
814             }
815             Ok(())
816         }
817     }
818 
819     #[cfg(all(
820         unix,
821         not(any(target_os = "solaris", target_os = "illumos")),
822         feature = "reuseport"
823     ))]
reuse_port(&self) -> io::Result<bool>824     pub fn reuse_port(&self) -> io::Result<bool> {
825         unsafe {
826             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_REUSEPORT)?;
827             Ok(raw != 0)
828         }
829     }
830 
831     #[cfg(all(
832         unix,
833         not(any(target_os = "solaris", target_os = "illumos")),
834         feature = "reuseport"
835     ))]
set_reuse_port(&self, reuse: bool) -> io::Result<()>836     pub fn set_reuse_port(&self, reuse: bool) -> io::Result<()> {
837         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_REUSEPORT, reuse as c_int) }
838     }
839 
out_of_band_inline(&self) -> io::Result<bool>840     pub fn out_of_band_inline(&self) -> io::Result<bool> {
841         unsafe {
842             let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_OOBINLINE)?;
843             Ok(raw != 0)
844         }
845     }
846 
set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()>847     pub fn set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()> {
848         unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_OOBINLINE, oob_inline as c_int) }
849     }
850 
setsockopt<T>(&self, opt: c_int, val: c_int, payload: T) -> io::Result<()> where T: Copy,851     unsafe fn setsockopt<T>(&self, opt: c_int, val: c_int, payload: T) -> io::Result<()>
852     where
853         T: Copy,
854     {
855         let payload = &payload as *const T as *const c_void;
856         cvt(libc::setsockopt(
857             self.fd,
858             opt,
859             val,
860             payload,
861             mem::size_of::<T>() as libc::socklen_t,
862         ))?;
863         Ok(())
864     }
865 
getsockopt<T: Copy>(&self, opt: c_int, val: c_int) -> io::Result<T>866     unsafe fn getsockopt<T: Copy>(&self, opt: c_int, val: c_int) -> io::Result<T> {
867         let mut slot: T = mem::zeroed();
868         let mut len = mem::size_of::<T>() as libc::socklen_t;
869         cvt(libc::getsockopt(
870             self.fd,
871             opt,
872             val,
873             &mut slot as *mut _ as *mut _,
874             &mut len,
875         ))?;
876         assert_eq!(len as usize, mem::size_of::<T>());
877         Ok(slot)
878     }
879 }
880 
881 impl Read for Socket {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>882     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
883         <&Socket>::read(&mut &*self, buf)
884     }
885 }
886 
887 impl<'a> Read for &'a Socket {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>888     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
889         unsafe {
890             let n = cvt({
891                 libc::read(
892                     self.fd,
893                     buf.as_mut_ptr() as *mut c_void,
894                     cmp::min(buf.len(), max_len()),
895                 )
896             })?;
897             Ok(n as usize)
898         }
899     }
900 }
901 
902 impl Write for Socket {
write(&mut self, buf: &[u8]) -> io::Result<usize>903     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
904         <&Socket>::write(&mut &*self, buf)
905     }
906 
flush(&mut self) -> io::Result<()>907     fn flush(&mut self) -> io::Result<()> {
908         <&Socket>::flush(&mut &*self)
909     }
910 }
911 
912 impl<'a> Write for &'a Socket {
write(&mut self, buf: &[u8]) -> io::Result<usize>913     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
914         self.send(buf, 0)
915     }
916 
flush(&mut self) -> io::Result<()>917     fn flush(&mut self) -> io::Result<()> {
918         Ok(())
919     }
920 }
921 
922 impl fmt::Debug for Socket {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result923     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
924         let mut f = f.debug_struct("Socket");
925         f.field("fd", &self.fd);
926         if let Ok(addr) = self.local_addr() {
927             f.field("local_addr", &addr);
928         }
929         if let Ok(addr) = self.peer_addr() {
930             f.field("peer_addr", &addr);
931         }
932         f.finish()
933     }
934 }
935 
936 impl AsRawFd for Socket {
as_raw_fd(&self) -> c_int937     fn as_raw_fd(&self) -> c_int {
938         self.fd
939     }
940 }
941 
942 impl IntoRawFd for Socket {
into_raw_fd(self) -> c_int943     fn into_raw_fd(self) -> c_int {
944         let fd = self.fd;
945         mem::forget(self);
946         return fd;
947     }
948 }
949 
950 impl FromRawFd for Socket {
from_raw_fd(fd: c_int) -> Socket951     unsafe fn from_raw_fd(fd: c_int) -> Socket {
952         Socket { fd: fd }
953     }
954 }
955 
956 impl AsRawFd for crate::Socket {
as_raw_fd(&self) -> c_int957     fn as_raw_fd(&self) -> c_int {
958         self.inner.as_raw_fd()
959     }
960 }
961 
962 impl IntoRawFd for crate::Socket {
into_raw_fd(self) -> c_int963     fn into_raw_fd(self) -> c_int {
964         self.inner.into_raw_fd()
965     }
966 }
967 
968 impl FromRawFd for crate::Socket {
from_raw_fd(fd: c_int) -> crate::Socket969     unsafe fn from_raw_fd(fd: c_int) -> crate::Socket {
970         crate::Socket {
971             inner: Socket::from_raw_fd(fd),
972         }
973     }
974 }
975 
976 impl Drop for Socket {
drop(&mut self)977     fn drop(&mut self) {
978         unsafe {
979             let _ = libc::close(self.fd);
980         }
981     }
982 }
983 
984 impl From<Socket> for net::TcpStream {
from(socket: Socket) -> net::TcpStream985     fn from(socket: Socket) -> net::TcpStream {
986         unsafe { net::TcpStream::from_raw_fd(socket.into_raw_fd()) }
987     }
988 }
989 
990 impl From<Socket> for net::TcpListener {
from(socket: Socket) -> net::TcpListener991     fn from(socket: Socket) -> net::TcpListener {
992         unsafe { net::TcpListener::from_raw_fd(socket.into_raw_fd()) }
993     }
994 }
995 
996 impl From<Socket> for net::UdpSocket {
from(socket: Socket) -> net::UdpSocket997     fn from(socket: Socket) -> net::UdpSocket {
998         unsafe { net::UdpSocket::from_raw_fd(socket.into_raw_fd()) }
999     }
1000 }
1001 
1002 #[cfg(all(unix, feature = "unix"))]
1003 impl From<Socket> for UnixStream {
from(socket: Socket) -> UnixStream1004     fn from(socket: Socket) -> UnixStream {
1005         unsafe { UnixStream::from_raw_fd(socket.into_raw_fd()) }
1006     }
1007 }
1008 
1009 #[cfg(all(unix, feature = "unix"))]
1010 impl From<Socket> for UnixListener {
from(socket: Socket) -> UnixListener1011     fn from(socket: Socket) -> UnixListener {
1012         unsafe { UnixListener::from_raw_fd(socket.into_raw_fd()) }
1013     }
1014 }
1015 
1016 #[cfg(all(unix, feature = "unix"))]
1017 impl From<Socket> for UnixDatagram {
from(socket: Socket) -> UnixDatagram1018     fn from(socket: Socket) -> UnixDatagram {
1019         unsafe { UnixDatagram::from_raw_fd(socket.into_raw_fd()) }
1020     }
1021 }
1022 
1023 impl From<net::TcpStream> for Socket {
from(socket: net::TcpStream) -> Socket1024     fn from(socket: net::TcpStream) -> Socket {
1025         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1026     }
1027 }
1028 
1029 impl From<net::TcpListener> for Socket {
from(socket: net::TcpListener) -> Socket1030     fn from(socket: net::TcpListener) -> Socket {
1031         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1032     }
1033 }
1034 
1035 impl From<net::UdpSocket> for Socket {
from(socket: net::UdpSocket) -> Socket1036     fn from(socket: net::UdpSocket) -> Socket {
1037         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1038     }
1039 }
1040 
1041 #[cfg(all(unix, feature = "unix"))]
1042 impl From<UnixStream> for Socket {
from(socket: UnixStream) -> Socket1043     fn from(socket: UnixStream) -> Socket {
1044         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1045     }
1046 }
1047 
1048 #[cfg(all(unix, feature = "unix"))]
1049 impl From<UnixListener> for Socket {
from(socket: UnixListener) -> Socket1050     fn from(socket: UnixListener) -> Socket {
1051         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1052     }
1053 }
1054 
1055 #[cfg(all(unix, feature = "unix"))]
1056 impl From<UnixDatagram> for Socket {
from(socket: UnixDatagram) -> Socket1057     fn from(socket: UnixDatagram) -> Socket {
1058         unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
1059     }
1060 }
1061 
max_len() -> usize1062 fn max_len() -> usize {
1063     // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
1064     // with the man page quoting that if the count of bytes to read is
1065     // greater than `SSIZE_MAX` the result is "unspecified".
1066     //
1067     // On macOS, however, apparently the 64-bit libc is either buggy or
1068     // intentionally showing odd behavior by rejecting any read with a size
1069     // larger than or equal to INT_MAX. To handle both of these the read
1070     // size is capped on both platforms.
1071     if cfg!(target_os = "macos") {
1072         <c_int>::max_value() as usize - 1
1073     } else {
1074         <ssize_t>::max_value() as usize
1075     }
1076 }
1077 
cvt<T: One + PartialEq + Neg<Output = T>>(t: T) -> io::Result<T>1078 fn cvt<T: One + PartialEq + Neg<Output = T>>(t: T) -> io::Result<T> {
1079     let one: T = T::one();
1080     if t == -one {
1081         Err(io::Error::last_os_error())
1082     } else {
1083         Ok(t)
1084     }
1085 }
1086 
cvt_r<F, T>(mut f: F) -> io::Result<T> where F: FnMut() -> T, T: One + PartialEq + Neg<Output = T>,1087 fn cvt_r<F, T>(mut f: F) -> io::Result<T>
1088 where
1089     F: FnMut() -> T,
1090     T: One + PartialEq + Neg<Output = T>,
1091 {
1092     loop {
1093         match cvt(f()) {
1094             Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
1095             other => return other,
1096         }
1097     }
1098 }
1099 
set_cloexec(fd: c_int) -> io::Result<()>1100 fn set_cloexec(fd: c_int) -> io::Result<()> {
1101     unsafe {
1102         let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?;
1103         let new = previous | libc::FD_CLOEXEC;
1104         if new != previous {
1105             cvt(libc::fcntl(fd, libc::F_SETFD, new))?;
1106         }
1107         Ok(())
1108     }
1109 }
1110 
dur2timeval(dur: Option<Duration>) -> io::Result<libc::timeval>1111 fn dur2timeval(dur: Option<Duration>) -> io::Result<libc::timeval> {
1112     match dur {
1113         Some(dur) => {
1114             if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
1115                 return Err(io::Error::new(
1116                     io::ErrorKind::InvalidInput,
1117                     "cannot set a 0 duration timeout",
1118                 ));
1119             }
1120 
1121             let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
1122                 libc::time_t::max_value()
1123             } else {
1124                 dur.as_secs() as libc::time_t
1125             };
1126             let mut timeout = libc::timeval {
1127                 tv_sec: secs,
1128                 tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t,
1129             };
1130             if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
1131                 timeout.tv_usec = 1;
1132             }
1133             Ok(timeout)
1134         }
1135         None => Ok(libc::timeval {
1136             tv_sec: 0,
1137             tv_usec: 0,
1138         }),
1139     }
1140 }
1141 
timeval2dur(raw: libc::timeval) -> Option<Duration>1142 fn timeval2dur(raw: libc::timeval) -> Option<Duration> {
1143     if raw.tv_sec == 0 && raw.tv_usec == 0 {
1144         None
1145     } else {
1146         let sec = raw.tv_sec as u64;
1147         let nsec = (raw.tv_usec as u32) * 1000;
1148         Some(Duration::new(sec, nsec))
1149     }
1150 }
1151 
to_s_addr(addr: &Ipv4Addr) -> libc::in_addr_t1152 fn to_s_addr(addr: &Ipv4Addr) -> libc::in_addr_t {
1153     let octets = addr.octets();
1154     crate::hton(
1155         ((octets[0] as libc::in_addr_t) << 24)
1156             | ((octets[1] as libc::in_addr_t) << 16)
1157             | ((octets[2] as libc::in_addr_t) << 8)
1158             | ((octets[3] as libc::in_addr_t) << 0),
1159     )
1160 }
1161 
from_s_addr(in_addr: libc::in_addr_t) -> Ipv4Addr1162 fn from_s_addr(in_addr: libc::in_addr_t) -> Ipv4Addr {
1163     let h_addr = crate::ntoh(in_addr);
1164 
1165     let a: u8 = (h_addr >> 24) as u8;
1166     let b: u8 = (h_addr >> 16) as u8;
1167     let c: u8 = (h_addr >> 8) as u8;
1168     let d: u8 = (h_addr >> 0) as u8;
1169 
1170     Ipv4Addr::new(a, b, c, d)
1171 }
1172 
to_in6_addr(addr: &Ipv6Addr) -> libc::in6_addr1173 fn to_in6_addr(addr: &Ipv6Addr) -> libc::in6_addr {
1174     let mut ret: libc::in6_addr = unsafe { mem::zeroed() };
1175     ret.s6_addr = addr.octets();
1176     return ret;
1177 }
1178 
1179 #[cfg(target_os = "android")]
to_ipv6mr_interface(value: u32) -> c_int1180 fn to_ipv6mr_interface(value: u32) -> c_int {
1181     value as c_int
1182 }
1183 
1184 #[cfg(not(target_os = "android"))]
to_ipv6mr_interface(value: u32) -> libc::c_uint1185 fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
1186     value as libc::c_uint
1187 }
1188 
linger2dur(linger_opt: libc::linger) -> Option<Duration>1189 fn linger2dur(linger_opt: libc::linger) -> Option<Duration> {
1190     if linger_opt.l_onoff == 0 {
1191         None
1192     } else {
1193         Some(Duration::from_secs(linger_opt.l_linger as u64))
1194     }
1195 }
1196 
dur2linger(dur: Option<Duration>) -> libc::linger1197 fn dur2linger(dur: Option<Duration>) -> libc::linger {
1198     match dur {
1199         Some(d) => libc::linger {
1200             l_onoff: 1,
1201             l_linger: d.as_secs() as c_int,
1202         },
1203         None => libc::linger {
1204             l_onoff: 0,
1205             l_linger: 0,
1206         },
1207     }
1208 }
1209 
1210 #[test]
test_ip()1211 fn test_ip() {
1212     let ip = Ipv4Addr::new(127, 0, 0, 1);
1213     assert_eq!(ip, from_s_addr(to_s_addr(&ip)));
1214 }
1215 
1216 #[test]
test_out_of_band_inline()1217 fn test_out_of_band_inline() {
1218     let tcp = Socket::new(libc::AF_INET, libc::SOCK_STREAM, 0).unwrap();
1219     assert_eq!(tcp.out_of_band_inline().unwrap(), false);
1220 
1221     tcp.set_out_of_band_inline(true).unwrap();
1222     assert_eq!(tcp.out_of_band_inline().unwrap(), true);
1223 }
1224