diff options
author | Marcin Mielniczuk <marmistrz.dev@zoho.eu> | 2017-08-03 10:32:44 +0200 |
---|---|---|
committer | Marcin Mielniczuk <marmistrz.dev@zoho.eu> | 2017-08-03 10:32:44 +0200 |
commit | ebcedb3bf98271fb77752acaec7a5c4990db578c (patch) | |
tree | e71f59ba68e4a672b865356e9f5ab0e54d7ed69b /src | |
parent | 9ad235c1e23e2bdf287b8f03550e6d54c4124db7 (diff) | |
parent | 607ab97ac64f597e78ab321aedd3063f8e040074 (diff) | |
download | nix-ebcedb3bf98271fb77752acaec7a5c4990db578c.zip |
Merge remote-tracking branch 'upstream/master' into ptrace-noreg
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/poll.rs | 82 | ||||
-rw-r--r-- | src/sys/socket/addr.rs | 246 | ||||
-rw-r--r-- | src/sys/socket/consts.rs | 437 | ||||
-rw-r--r-- | src/sys/socket/mod.rs | 152 | ||||
-rw-r--r-- | src/sys/socket/sockopt.rs | 79 |
6 files changed, 446 insertions, 551 deletions
@@ -39,7 +39,6 @@ pub mod mqueue; pub mod pty; -#[cfg(any(target_os = "linux", target_os = "macos"))] pub mod poll; pub mod net; diff --git a/src/poll.rs b/src/poll.rs index afc5bd9c..60c31ace 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -1,11 +1,20 @@ -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::time::TimeSpec; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::signal::SigSet; +use std::os::unix::io::RawFd; use libc; use {Errno, Result}; +/// This is a wrapper around `libc::pollfd`. +/// +/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and +/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest +/// for a specific file descriptor. +/// +/// After a call to `poll` or `ppoll`, the events that occured can be +/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. #[repr(C)] #[derive(Clone, Copy)] pub struct PollFd { @@ -13,7 +22,9 @@ pub struct PollFd { } impl PollFd { - pub fn new(fd: libc::c_int, events: EventFlags) -> PollFd { + /// Creates a new `PollFd` specifying the events of interest + /// for a given file descriptor. + pub fn new(fd: RawFd, events: EventFlags) -> PollFd { PollFd { pollfd: libc::pollfd { fd: fd, @@ -23,26 +34,82 @@ impl PollFd { } } + /// Returns the events that occured in the last call to `poll` or `ppoll`. pub fn revents(&self) -> Option<EventFlags> { EventFlags::from_bits(self.pollfd.revents) } } libc_bitflags! { + /// These flags define the different events that can be monitored by `poll` and `ppoll` pub flags EventFlags: libc::c_short { + /// There is data to read. POLLIN, + /// There is some exceptional condition on the file descriptor. + /// + /// Possibilities include: + /// + /// * There is out-of-band data on a TCP socket (see + /// [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)). + /// * A pseudoterminal master in packet mode has seen a state + /// change on the slave (see + /// [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)). + /// * A cgroup.events file has been modified (see + /// [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)). POLLPRI, + /// Writing is now possible, though a write larger that the + /// available space in a socket or pipe will still block (unless + /// `O_NONBLOCK` is set). POLLOUT, + /// Equivalent to [`POLLIN`](constant.POLLIN.html) POLLRDNORM, + /// Equivalent to [`POLLOUT`](constant.POLLOUT.html) POLLWRNORM, + /// Priority band data can be read (generally unused on Linux). POLLRDBAND, + /// Priority data may be written. POLLWRBAND, + /// Error condition (only returned in + /// [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). + /// This bit is also set for a file descriptor referring to the + /// write end of a pipe when the read end has been closed. POLLERR, + /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). + /// Note that when reading from a channel such as a pipe or a stream + /// socket, this event merely indicates that the peer closed its + /// end of the channel. Subsequent reads from the channel will + /// return 0 (end of file) only after all outstanding data in the + /// channel has been consumed. POLLHUP, + /// Invalid request: `fd` not open (only returned in + /// [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). POLLNVAL, } } +/// `poll` waits for one of a set of file descriptors to become ready to perform I/O. +/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html)) +/// +/// `fds` contains all [`PollFd`](struct.PollFd.html) to poll. +/// The function will return as soon as any event occur for any of these `PollFd`s. +/// +/// The `timeout` argument specifies the number of milliseconds that `poll()` +/// should block waiting for a file descriptor to become ready. The call +/// will block until either: +/// +/// * a file descriptor becomes ready; +/// * the call is interrupted by a signal handler; or +/// * the timeout expires. +/// +/// Note that the timeout interval will be rounded up to the system clock +/// granularity, and kernel scheduling delays mean that the blocking +/// interval may overrun by a small amount. Specifying a negative value +/// in timeout means an infinite timeout. Specifying a timeout of zero +/// causes `poll()` to return immediately, even if no file descriptors are +/// ready. pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> { let res = unsafe { libc::poll(fds.as_mut_ptr() as *mut libc::pollfd, @@ -53,7 +120,14 @@ pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> { Errno::result(res) } -#[cfg(any(target_os = "linux", target_os = "android"))] +/// `ppoll()` allows an application to safely wait until either a file +/// descriptor becomes ready or until a signal is caught. +/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html)) +/// +/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it +/// with the `sigmask` argument. +/// +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> { diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 5f8b130a..71001534 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -1,37 +1,204 @@ -use super::{consts, sa_family_t}; +use super::sa_family_t; use {Errno, Error, Result, NixPath}; use libc; use std::{fmt, hash, mem, net, ptr}; use std::ffi::OsStr; use std::path::Path; use std::os::unix::ffi::OsStrExt; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "linux"))] use ::sys::socket::addr::netlink::NetlinkAddr; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "ios", target_os = "macos"))] use std::os::unix::io::RawFd; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "ios", target_os = "macos"))] use ::sys::socket::addr::sys_control::SysControlAddr; -// TODO: uncomment out IpAddr functions: rust-lang/rfcs#988 - -/* - * - * ===== AddressFamily ===== - * - */ - +/// These constants specify the protocol family to be used +/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) #[repr(i32)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum AddressFamily { - Unix = consts::AF_UNIX, - Inet = consts::AF_INET, - Inet6 = consts::AF_INET6, - #[cfg(any(target_os = "linux", target_os = "android"))] - Netlink = consts::AF_NETLINK, - #[cfg(any(target_os = "linux", target_os = "android"))] - Packet = consts::AF_PACKET, - #[cfg(any(target_os = "macos", target_os = "ios"))] - System = consts::AF_SYSTEM, + /// Local communication (see [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html)) + Unix = libc::AF_UNIX, + /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html)) + Inet = libc::AF_INET, + /// IPv6 Internet protocols (see [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html)) + Inet6 = libc::AF_INET6, + /// Kernel user interface device (see [`netlink(7)`](http://man7.org/linux/man-pages/man7/netlink.7.html)) + #[cfg(any(target_os = "android", target_os = "linux"))] + Netlink = libc::AF_NETLINK, + /// Low level packet interface (see [`packet(7)`](http://man7.org/linux/man-pages/man7/packet.7.html)) + #[cfg(any(target_os = "android", target_os = "linux"))] + Packet = libc::AF_PACKET, + /// KEXT Controls and Notifications + #[cfg(any(target_os = "ios", target_os = "macos"))] + System = libc::AF_SYSTEM, + /// Amateur radio AX.25 protocol + #[cfg(any(target_os = "android", target_os = "linux"))] + Ax25 = libc::AF_AX25, + /// IPX - Novell protocols + Ipx = libc::AF_IPX, + /// AppleTalk + AppleTalk = libc::AF_APPLETALK, + #[cfg(any(target_os = "android", target_os = "linux"))] + NetRom = libc::AF_NETROM, + #[cfg(any(target_os = "android", target_os = "linux"))] + Bridge = libc::AF_BRIDGE, + /// Access to raw ATM PVCs + #[cfg(any(target_os = "android", target_os = "linux"))] + AtmPvc = libc::AF_ATMPVC, + /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](http://man7.org/linux/man-pages/man7/x25.7.html)) + #[cfg(any(target_os = "android", target_os = "linux"))] + X25 = libc::AF_X25, + #[cfg(any(target_os = "android", target_os = "linux"))] + Rose = libc::AF_ROSE, + Decnet = libc::AF_DECnet, + #[cfg(any(target_os = "android", target_os = "linux"))] + NetBeui = libc::AF_NETBEUI, + #[cfg(any(target_os = "android", target_os = "linux"))] + Security = libc::AF_SECURITY, + #[cfg(any(target_os = "android", target_os = "linux"))] + Key = libc::AF_KEY, + #[cfg(any(target_os = "android", target_os = "linux"))] + Ash = libc::AF_ASH, + #[cfg(any(target_os = "android", target_os = "linux"))] + Econet = libc::AF_ECONET, + #[cfg(any(target_os = "android", target_os = "linux"))] + AtmSvc = libc::AF_ATMSVC, + #[cfg(any(target_os = "android", target_os = "linux"))] + Rds = libc::AF_RDS, + Sna = libc::AF_SNA, + #[cfg(any(target_os = "android", target_os = "linux"))] + Irda = libc::AF_IRDA, + #[cfg(any(target_os = "android", target_os = "linux"))] + Pppox = libc::AF_PPPOX, + #[cfg(any(target_os = "android", target_os = "linux"))] + Wanpipe = libc::AF_WANPIPE, + #[cfg(any(target_os = "android", target_os = "linux"))] + Llc = libc::AF_LLC, + #[cfg(target_os = "linux")] + Ib = libc::AF_IB, + #[cfg(target_os = "linux")] + Mpls = libc::AF_MPLS, + #[cfg(any(target_os = "android", target_os = "linux"))] + Can = libc::AF_CAN, + #[cfg(any(target_os = "android", target_os = "linux"))] + Tipc = libc::AF_TIPC, + #[cfg(not(any(target_os = "ios", target_os = "macos")))] + Bluetooth = libc::AF_BLUETOOTH, + #[cfg(any(target_os = "android", target_os = "linux"))] + Iucv = libc::AF_IUCV, + #[cfg(any(target_os = "android", target_os = "linux"))] + RxRpc = libc::AF_RXRPC, + Isdn = libc::AF_ISDN, + #[cfg(any(target_os = "android", target_os = "linux"))] + Phonet = libc::AF_PHONET, + #[cfg(any(target_os = "android", target_os = "linux"))] + Ieee802154 = libc::AF_IEEE802154, + #[cfg(any(target_os = "android", target_os = "linux"))] + Caif = libc::AF_CAIF, + /// Interface to kernel crypto API + #[cfg(any(target_os = "android", target_os = "linux"))] + Alg = libc::AF_ALG, + #[cfg(target_os = "linux")] + Nfc = libc::AF_NFC, + #[cfg(target_os = "linux")] + Vsock = libc::AF_VSOCK, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + ImpLink = libc::AF_IMPLINK, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Pup = libc::AF_PUP, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Chaos = libc::AF_CHAOS, + #[cfg(any(target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Ns = libc::AF_NS, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Iso = libc::AF_ISO, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Datakit = libc::AF_DATAKIT, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Ccitt = libc::AF_CCITT, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Dli = libc::AF_DLI, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Lat = libc::AF_LAT, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Hylink = libc::AF_HYLINK, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Link = libc::AF_LINK, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Coip = libc::AF_COIP, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Cnt = libc::AF_CNT, + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] + Natm = libc::AF_NATM, } #[derive(Copy)] @@ -252,7 +419,7 @@ impl Ipv4Addr { } pub fn any() -> Ipv4Addr { - Ipv4Addr(libc::in_addr { s_addr: consts::INADDR_ANY }) + Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY }) } pub fn octets(&self) -> [u8; 4] { @@ -480,9 +647,9 @@ impl fmt::Display for UnixAddr { pub enum SockAddr { Inet(InetAddr), Unix(UnixAddr), - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] Netlink(NetlinkAddr), - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] SysControl(SysControlAddr), } @@ -495,12 +662,12 @@ impl SockAddr { Ok(SockAddr::Unix(try!(UnixAddr::new(path)))) } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] pub fn new_netlink(pid: u32, groups: u32) -> SockAddr { SockAddr::Netlink(NetlinkAddr::new(pid, groups)) } - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> { SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a)) } @@ -510,9 +677,9 @@ impl SockAddr { SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet, SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6, SockAddr::Unix(..) => AddressFamily::Unix, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] SockAddr::Netlink(..) => AddressFamily::Netlink, - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] SockAddr::SysControl(..) => AddressFamily::System, } } @@ -526,9 +693,9 @@ impl SockAddr { SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t), SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t), SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t), - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t), - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t), } } @@ -543,7 +710,7 @@ impl PartialEq for SockAddr { (SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => { a == b } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] (SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => { a == b } @@ -560,9 +727,9 @@ impl hash::Hash for SockAddr { match *self { SockAddr::Inet(ref a) => a.hash(s), SockAddr::Unix(ref a) => a.hash(s), - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] SockAddr::Netlink(ref a) => a.hash(s), - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] SockAddr::SysControl(ref a) => a.hash(s), } } @@ -579,15 +746,15 @@ impl fmt::Display for SockAddr { match *self { SockAddr::Inet(ref inet) => inet.fmt(f), SockAddr::Unix(ref unix) => unix.fmt(f), - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] SockAddr::Netlink(ref nl) => nl.fmt(f), - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(any(target_os = "ios", target_os = "macos"))] SockAddr::SysControl(ref sc) => sc.fmt(f), } } } -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "linux"))] pub mod netlink { use ::sys::socket::addr::{AddressFamily}; use libc::{sa_family_t, sockaddr_nl}; @@ -642,11 +809,10 @@ pub mod netlink { } } -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "ios", target_os = "macos"))] pub mod sys_control { - use ::sys::socket::consts; use ::sys::socket::addr::{AddressFamily}; - use libc::{c_uchar, uint16_t, uint32_t}; + use libc::{self, c_uchar, uint16_t, uint32_t}; use std::{fmt, mem}; use std::hash::{Hash, Hasher}; use std::os::unix::io::RawFd; @@ -702,7 +868,7 @@ pub mod sys_control { let addr = sockaddr_ctl { sc_len: mem::size_of::<sockaddr_ctl>() as c_uchar, sc_family: AddressFamily::System as c_uchar, - ss_sysaddr: consts::AF_SYS_CONTROL as uint16_t, + ss_sysaddr: libc::AF_SYS_CONTROL as uint16_t, sc_id: id, sc_unit: unit, sc_reserved: [0; 5] diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs deleted file mode 100644 index ad9c522f..00000000 --- a/src/sys/socket/consts.rs +++ /dev/null @@ -1,437 +0,0 @@ -pub use self::os::*; - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod os { - use libc::{self, c_int, uint8_t}; - - pub const AF_UNIX: c_int = libc::AF_UNIX; - pub const AF_LOCAL: c_int = libc::AF_LOCAL; - pub const AF_INET: c_int = libc::AF_INET; - pub const AF_INET6: c_int = libc::AF_INET6; - pub const AF_NETLINK: c_int = libc::AF_NETLINK; - pub const AF_PACKET: c_int = libc::AF_PACKET; - - pub const SOCK_STREAM: c_int = libc::SOCK_STREAM; - pub const SOCK_DGRAM: c_int = libc::SOCK_DGRAM; - pub const SOCK_SEQPACKET: c_int = libc::SOCK_SEQPACKET; - pub const SOCK_RAW: c_int = libc::SOCK_RAW; - pub const SOCK_RDM: c_int = 4; - - pub const SOL_IP: c_int = libc::SOL_IP; - pub const SOL_SOCKET: c_int = libc::SOL_SOCKET; - pub const SOL_TCP: c_int = libc::SOL_TCP; - pub const SOL_UDP: c_int = 17; - pub const SOL_IPV6: c_int = libc::SOL_IPV6; - pub const SOL_NETLINK: c_int = libc::SOL_NETLINK; - pub const IPPROTO_IP: c_int = libc::IPPROTO_IP; - pub const IPPROTO_IPV6: c_int = libc::IPPROTO_IPV6; - pub const IPPROTO_TCP: c_int = libc::IPPROTO_TCP; - pub const IPPROTO_UDP: c_int = SOL_UDP; - - pub const SO_ACCEPTCONN: c_int = libc::SO_ACCEPTCONN; - pub const SO_BINDTODEVICE: c_int = libc::SO_BINDTODEVICE; - pub const SO_BROADCAST: c_int = libc::SO_BROADCAST; - pub const SO_BSDCOMPAT: c_int = libc::SO_BSDCOMPAT; - pub const SO_DEBUG: c_int = libc::SO_DEBUG; - pub const SO_DOMAIN: c_int = libc::SO_DOMAIN; - pub const SO_ERROR: c_int = libc::SO_ERROR; - pub const SO_DONTROUTE: c_int = libc::SO_DONTROUTE; - pub const SO_KEEPALIVE: c_int = libc::SO_KEEPALIVE; - pub const SO_LINGER: c_int = libc::SO_LINGER; - pub const SO_MARK: c_int = libc::SO_MARK; - pub const SO_OOBINLINE: c_int = libc::SO_OOBINLINE; - pub const SO_PASSCRED: c_int = libc::SO_PASSCRED; - pub const SO_PEEK_OFF: c_int = libc::SO_PEEK_OFF; - pub const SO_PEERCRED: c_int = libc::SO_PEERCRED; - pub const SO_PRIORITY: c_int = libc::SO_PRIORITY; - pub const SO_PROTOCOL: c_int = libc::SO_PROTOCOL; - pub const SO_RCVBUF: c_int = libc::SO_RCVBUF; - pub const SO_RCVBUFFORCE: c_int = 33; - pub const SO_RCVLOWAT: c_int = libc::SO_RCVLOWAT; - pub const SO_SNDLOWAT: c_int = libc::SO_SNDLOWAT; - pub const SO_RCVTIMEO: c_int = libc::SO_RCVTIMEO; - pub const SO_SNDTIMEO: c_int = libc::SO_SNDTIMEO; - pub const SO_REUSEADDR: c_int = libc::SO_REUSEADDR; - pub const SO_REUSEPORT: c_int = libc::SO_REUSEPORT; - pub const SO_RXQ_OVFL: c_int = libc::SO_RXQ_OVFL; - pub const SO_SNDBUF: c_int = libc::SO_SNDBUF; - pub const SO_SNDBUFFORCE: c_int = libc::SO_SNDBUFFORCE; - pub const SO_TIMESTAMP: c_int = libc::SO_TIMESTAMP; - pub const SO_TYPE: c_int = libc::SO_TYPE; - pub const SO_BUSY_POLL: c_int = libc::SO_BUSY_POLL; - #[cfg(target_os = "linux")] - pub const SO_ORIGINAL_DST: c_int = 80; - - // Socket options for TCP sockets - pub const TCP_NODELAY: c_int = libc::TCP_NODELAY; - pub const TCP_MAXSEG: c_int = libc::TCP_MAXSEG; - pub const TCP_CORK: c_int = libc::TCP_CORK; - pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE; - - // Socket options for the IP layer of the socket - pub const IP_MULTICAST_IF: c_int = 32; - - pub type IpMulticastTtl = uint8_t; - - pub const IP_MULTICAST_TTL: c_int = libc::IP_MULTICAST_TTL; - pub const IP_MULTICAST_LOOP: c_int = libc::IP_MULTICAST_LOOP; - pub const IP_ADD_MEMBERSHIP: c_int = libc::IP_ADD_MEMBERSHIP; - pub const IP_DROP_MEMBERSHIP: c_int = libc::IP_DROP_MEMBERSHIP; - - pub const IPV6_ADD_MEMBERSHIP: c_int = libc::IPV6_ADD_MEMBERSHIP; - pub const IPV6_DROP_MEMBERSHIP: c_int = libc::IPV6_DROP_MEMBERSHIP; - - pub type InAddrT = u32; - - // Declarations of special addresses - pub const INADDR_ANY: InAddrT = 0; - pub const INADDR_NONE: InAddrT = 0xffffffff; - pub const INADDR_BROADCAST: InAddrT = 0xffffffff; - - // Flags for send/recv and their relatives - libc_bitflags!{ - pub flags MsgFlags: libc::c_int { - MSG_OOB, - MSG_PEEK, - MSG_CTRUNC, - MSG_TRUNC, - MSG_DONTWAIT, - MSG_EOR, - MSG_ERRQUEUE, - MSG_CMSG_CLOEXEC, - } - } - - // shutdown flags - pub const SHUT_RD: c_int = libc::SHUT_RD; - pub const SHUT_WR: c_int = libc::SHUT_WR; - pub const SHUT_RDWR: c_int = libc::SHUT_RDWR; - - // Ancillary message types - pub const SCM_RIGHTS: c_int = libc::SCM_RIGHTS; -} - -// Not all of these constants exist on freebsd -#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))] -mod os { - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"))] - use libc::{self, c_int, uint8_t}; - #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] - use libc::{self, c_int, uint8_t}; - - pub const AF_UNIX: c_int = libc::AF_UNIX; - pub const AF_LOCAL: c_int = libc::AF_LOCAL; - pub const AF_INET: c_int = libc::AF_INET; - pub const AF_INET6: c_int = libc::AF_INET6; - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const AF_SYSTEM: c_int = libc::AF_SYSTEM; - - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const AF_SYS_CONTROL: c_int = 2; - - pub const SOCK_STREAM: c_int = libc::SOCK_STREAM; - pub const SOCK_DGRAM: c_int = libc::SOCK_DGRAM; - pub const SOCK_SEQPACKET: c_int = libc::SOCK_SEQPACKET; - pub const SOCK_RAW: c_int = libc::SOCK_RAW; - pub const SOCK_RDM: c_int = libc::SOCK_RDM; - - pub const SOL_SOCKET: c_int = libc::SOL_SOCKET; - pub const IPPROTO_IP: c_int = libc::IPPROTO_IP; - pub const IPPROTO_IPV6: c_int = libc::IPPROTO_IPV6; - pub const IPPROTO_TCP: c_int = libc::IPPROTO_TCP; - pub const IPPROTO_UDP: c_int = 17; - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const SYSPROTO_CONTROL: c_int = 2; - - pub const SO_ACCEPTCONN: c_int = libc::SO_ACCEPTCONN; - pub const SO_BROADCAST: c_int = libc::SO_BROADCAST; - pub const SO_DEBUG: c_int = libc::SO_DEBUG; - #[cfg(not(target_os = "netbsd"))] - pub const SO_DONTTRUNC: c_int = 0x2000; - pub const SO_USELOOPBACK: c_int = libc::SO_USELOOPBACK; - pub const SO_ERROR: c_int = libc::SO_ERROR; - pub const SO_DONTROUTE: c_int = libc::SO_DONTROUTE; - pub const SO_KEEPALIVE: c_int = libc::SO_KEEPALIVE; - pub const SO_LABEL: c_int = 0x1010; - pub const SO_LINGER: c_int = libc::SO_LINGER; - pub const SO_NREAD: c_int = 0x1020; - pub const SO_NKE: c_int = 0x1021; - pub const SO_NOSIGPIPE: c_int = 0x1022; - pub const SO_NOADDRERR: c_int = 0x1023; - pub const SO_NOTIFYCONFLICT: c_int = 0x1026; - pub const SO_NP_EXTENSIONS: c_int = 0x1083; - pub const SO_NWRITE: c_int = 0x1024; - pub const SO_OOBINLINE: c_int = libc::SO_OOBINLINE; - pub const SO_PEERLABEL: c_int = 0x1011; - pub const SO_RCVBUF: c_int = libc::SO_RCVBUF; - pub const SO_RCVLOWAT: c_int = libc::SO_RCVLOWAT; - pub const SO_SNDLOWAT: c_int = libc::SO_SNDLOWAT; - pub const SO_RCVTIMEO: c_int = libc::SO_RCVTIMEO; - pub const SO_SNDTIMEO: c_int = libc::SO_SNDTIMEO; - pub const SO_RANDOMPORT: c_int = 0x1082; - pub const SO_RESTRICTIONS: c_int = 0x1081; - pub const SO_RESTRICT_DENYIN: c_int = 0x00000001; - pub const SO_RESTRICT_DENYOUT: c_int = 0x00000002; - pub const SO_REUSEADDR: c_int = libc::SO_REUSEADDR; - pub const SO_REUSEPORT: c_int = libc::SO_REUSEPORT; - pub const SO_REUSESHAREUID: c_int = 0x1025; - pub const SO_SNDBUF: c_int = libc::SO_SNDBUF; - pub const SO_TIMESTAMP: c_int = libc::SO_TIMESTAMP; - #[cfg(not(target_os = "netbsd"))] - pub const SO_TIMESTAMP_MONOTONIC: c_int = 0x0800; - pub const SO_TYPE: c_int = libc::SO_TYPE; - #[cfg(not(target_os = "netbsd"))] - pub const SO_WANTMORE: c_int = 0x4000; - pub const SO_WANTOOBFLAG: c_int = 0x8000; - #[allow(overflowing_literals)] - pub const SO_RESTRICT_DENYSET: c_int = 0x80000000; - - // Socket options for TCP sockets - pub const TCP_NODELAY: c_int = libc::TCP_NODELAY; - pub const TCP_MAXSEG: c_int = 2; - #[cfg(any(target_os = "macos", target_os = "ios"))] - pub const TCP_KEEPALIVE: c_int = libc::TCP_KEEPALIVE; - #[cfg(target_os = "freebsd")] - pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE; - - // Socket options for the IP layer of the socket - pub const IP_MULTICAST_IF: c_int = 9; - - pub type IpMulticastTtl = uint8_t; - - pub const IP_MULTICAST_TTL: c_int = libc::IP_MULTICAST_TTL; - pub const IP_MULTICAST_LOOP: c_int = libc::IP_MULTICAST_LOOP; - pub const IP_ADD_MEMBERSHIP: c_int = libc::IP_ADD_MEMBERSHIP; - pub const IP_DROP_MEMBERSHIP: c_int = libc::IP_DROP_MEMBERSHIP; - - pub const IPV6_JOIN_GROUP: c_int = libc::IPV6_JOIN_GROUP; - pub const IPV6_LEAVE_GROUP: c_int = libc::IPV6_LEAVE_GROUP; - - pub type InAddrT = u32; - - // Declarations of special addresses - pub const INADDR_ANY: InAddrT = 0; - pub const INADDR_NONE: InAddrT = 0xffffffff; - pub const INADDR_BROADCAST: InAddrT = 0xffffffff; - - // Flags for send/recv and their relatives - libc_bitflags!{ - pub flags MsgFlags: libc::c_int { - MSG_OOB, - MSG_PEEK, - MSG_EOR, - MSG_TRUNC, - MSG_CTRUNC, - MSG_DONTWAIT, - } - } - - // shutdown flags - pub const SHUT_RD: c_int = libc::SHUT_RD; - pub const SHUT_WR: c_int = libc::SHUT_WR; - pub const SHUT_RDWR: c_int = libc::SHUT_RDWR; - - // Ancillary message types - pub const SCM_RIGHTS: c_int = 1; -} - -#[cfg(target_os = "dragonfly")] -mod os { - use libc::{c_int, uint8_t}; - - pub const AF_UNIX: c_int = libc::AF_UNIX; - pub const AF_LOCAL: c_int = libc::AF_LOCAL; - pub const AF_INET: c_int = libc::AF_INET; - pub const AF_INET6: c_int = libc::AF_INET6; - - pub const SOCK_STREAM: c_int = libc::SOCK_STREAM; - pub const SOCK_DGRAM: c_int = libc::SOCK_DGRAM; - pub const SOCK_SEQPACKET: c_int = libc::SOCK_SEQPACKET; - pub const SOCK_RAW: c_int = libc::SOCK_RAW; - pub const SOCK_RDM: c_int = libc::SOCK_RDM; - - pub const SOL_SOCKET: c_int = libc::SOL_SOCKET; - pub const IPPROTO_IP: c_int = libc::IPPROTO_IP; - pub const IPPROTO_IPV6: c_int = libc::IPPROTO_IPV6; - pub const IPPROTO_TCP: c_int = libc::IPPROTO_TCP; - pub const IPPROTO_UDP: c_int = libc::IPPROTO_UDP; - - pub const SO_ACCEPTCONN: c_int = libc::SO_ACCEPTCONN; - pub const SO_BROADCAST: c_int = libc::SO_BROADCAST; - pub const SO_DEBUG: c_int = libc::SO_DEBUG; - pub const SO_ERROR: c_int = libc::SO_ERROR; - pub const SO_DONTROUTE: c_int = libc::SO_DONTROUTE; - pub const SO_KEEPALIVE: c_int = libc::SO_KEEPALIVE; - pub const SO_LINGER: c_int = libc::SO_LINGER; - pub const SO_NOSIGPIPE: c_int = libc::SO_NOSIGPIPE; - pub const SO_OOBINLINE: c_int = libc::SO_OOBINLINE; - pub const SO_RCVBUF: c_int = libc::SO_RCVBUF; - pub const SO_RCVLOWAT: c_int = libc::RCVLOWAT; - pub const SO_SNDLOWAT: c_int = libc::SO_SNDLOWAT; - pub const SO_RCVTIMEO: c_int = libc::SO_RCVTIMEO; - pub const SO_SNDTIMEO: c_int = libc::SO_SNDTIMEO; - pub const SO_REUSEADDR: c_int = libc::SO_REUSEADDR; - pub const SO_REUSEPORT: c_int = libc::SO_REUSEPORT; - pub const SO_SNDBUF: c_int = libc::SO_SNDBUF; - pub const SO_TIMESTAMP: c_int = libc::SO_TIMESTAMP; - pub const SO_TYPE: c_int = libc::SO_TYPE; - - // Socket options for TCP sockets - pub const TCP_NODELAY: c_int = libc::TCP_NODELAY; - pub const TCP_MAXSEG: c_int = libc::TCP_MAXSEG; - pub const TCP_KEEPIDLE: c_int = libc::TCP_KEEPIDLE; - - // Socket options for the IP layer of the socket - pub const IP_MULTICAST_IF: c_int = 9; - - pub type IpMulticastTtl = uint8_t; - - pub const IP_MULTICAST_TTL: c_int = libc::IP_MULTICAST_TTL; - pub const IP_MULTICAST_LOOP: c_int = libc::IP_MULTICAST_LOOP; - pub const IP_ADD_MEMBERSHIP: c_int = libc::IP_ADD_MEMBERSHIP; - pub const IP_DROP_MEMBERSHIP: c_int = libc::IP_DROP_MEMBERSHIP; - pub const IPV6_JOIN_GROUP: c_int = libc::IPV6_JOIN_GROUP; - pub const IPV6_LEAVE_GROUP: c_int = libc::IPV6_LEAVE_GROUP; - - pub type InAddrT = u32; - - // Declarations of special addresses - pub const INADDR_ANY: InAddrT = 0; - pub const INADDR_NONE: InAddrT = 0xffffffff; - pub const INADDR_BROADCAST: InAddrT = 0xffffffff; - - // Flags for send/recv and their relatives - libc_bitflags!{ - pub flags MsgFlags: libc::c_int { - MSG_OOB, - MSG_PEEK, - MSG_DONTWAIT, - } - } - - // shutdown flags - pub const SHUT_RD: c_int = libc::SHUT_RD; - pub const SHUT_WR: c_int = libc::SHUT_WR; - pub const SHUT_RDWR: c_int = libc::SHUT_RDWR; -} - -#[cfg(test)] -mod test { - use super::*; - use nixtest::{assert_const_eq,get_int_const,GetConst}; - use libc::{c_char}; - use std::fmt; - - impl fmt::Display for MsgFlags { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.bits()) - } - } - - impl GetConst for MsgFlags { - unsafe fn get_const(name: *const c_char) -> MsgFlags { - MsgFlags::from_bits_truncate(get_int_const(name)) - } - } - - macro_rules! check_const { - ($($konst:ident),+) => {{ - $(assert_const_eq(stringify!($konst), $konst);)+ - }}; - } - - #[test] - pub fn test_const_values() { - check_const!( - AF_UNIX, - AF_LOCAL, - AF_INET, - AF_INET6, - SOCK_STREAM, - SOCK_DGRAM, - SOCK_SEQPACKET, - SOCK_RAW, - SOCK_RDM, - SOL_SOCKET, - IPPROTO_IP, - IPPROTO_IPV6, - IPPROTO_TCP, - IPPROTO_UDP, - SO_ACCEPTCONN, - SO_BROADCAST, - SO_DEBUG, - SO_ERROR, - SO_DONTROUTE, - SO_KEEPALIVE, - SO_LINGER, - SO_OOBINLINE, - SO_RCVBUF, - SO_RCVLOWAT, - SO_SNDLOWAT, - SO_RCVTIMEO, - SO_SNDTIMEO, - SO_REUSEADDR, - // SO_REUSEPORT, - SO_SNDBUF, - SO_TIMESTAMP, - SO_TYPE, - TCP_NODELAY, - TCP_MAXSEG, - IP_MULTICAST_IF, - IP_MULTICAST_TTL, - IP_MULTICAST_LOOP, - IP_ADD_MEMBERSHIP, - IP_DROP_MEMBERSHIP, - INADDR_ANY, - INADDR_NONE, - INADDR_BROADCAST, - MSG_OOB, - MSG_PEEK, - MSG_DONTWAIT, - MSG_EOR, - MSG_TRUNC, - MSG_CTRUNC, - SHUT_RD, - SHUT_WR, - SHUT_RDWR - ); - - - } - - #[cfg(target_os = "linux")] - #[test] - pub fn test_general_linux_consts() { - // TODO Figure out how to test new constants - check_const!( - SOL_IP, - SOL_TCP, - SOL_UDP, - SOL_IPV6, - SO_BINDTODEVICE, - SO_BSDCOMPAT, - // SO_DOMAIN, - // SO_MARK, - TCP_CORK, - // SO_BUSY_POLL, - // SO_RXQ_OVFL, - SO_PRIORITY, - // SO_PROTOCOL, - SO_RCVBUFFORCE, - // SO_PEEK_OFF, - MSG_ERRQUEUE); - } - - #[cfg(all(target_os = "linux", not(target_arch="arm")))] - #[test] - pub fn test_linux_not_arm_consts() { - // TODO Figure out how to test new constants - check_const!( - SO_PASSCRED, - SO_PEERCRED, - SO_SNDBUFFORCE); - } - -} diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index c11b5367..86129fcf 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -5,13 +5,12 @@ use {Error, Errno, Result}; use features; use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; -use libc::{c_void, c_int, socklen_t, size_t, pid_t, uid_t, gid_t}; +use libc::{self, c_void, c_int, socklen_t, size_t, pid_t, uid_t, gid_t}; use std::{mem, ptr, slice}; use std::os::unix::io::RawFd; use sys::uio::IoVec; mod addr; -mod consts; mod ffi; mod multicast; pub mod sockopt; @@ -48,28 +47,112 @@ pub use self::multicast::{ ip_mreq, ipv6_mreq, }; -pub use self::consts::*; pub use libc::sockaddr_storage; +/// These constants are used to specify the communication semantics +/// when creating a socket with [`socket()`](fn.socket.html) #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[repr(i32)] pub enum SockType { - Stream = consts::SOCK_STREAM, - Datagram = consts::SOCK_DGRAM, - SeqPacket = consts::SOCK_SEQPACKET, - Raw = consts::SOCK_RAW, - Rdm = consts::SOCK_RDM, + /// Provides sequenced, reliable, two-way, connection- + /// based byte streams. An out-of-band data transmission + /// mechanism may be supported. + Stream = libc::SOCK_STREAM, + /// Supports datagrams (connectionless, unreliable + /// messages of a fixed maximum length). + Datagram = libc::SOCK_DGRAM, + /// Provides a sequenced, reliable, two-way connection- + /// based data transmission path for datagrams of fixed + /// maximum length; a consumer is required to read an + /// entire packet with each input system call. + SeqPacket = libc::SOCK_SEQPACKET, + /// Provides raw network protocol access. + Raw = libc::SOCK_RAW, + /// Provides a reliable datagram layer that does not + /// guarantee ordering. + Rdm = libc::SOCK_RDM, +} + +/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) +/// to specify the protocol to use. +#[repr(i32)] +pub enum SockProtocol { + /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html)) + Tcp = libc::IPPROTO_TCP, + /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html)) + Udp = libc::IPPROTO_UDP, + /// Allows applications and other KEXTs to be notified when certain kernel events occur + /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html)) + #[cfg(any(target_os = "ios", target_os = "macos"))] + KextEvent = libc::SYSPROTO_EVENT, + /// Allows applications to configure and control a KEXT + /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html)) + #[cfg(any(target_os = "ios", target_os = "macos"))] + KextControl = libc::SYSPROTO_CONTROL, } -// Extra flags - Supported by Linux 2.6.27, normalized on other platforms bitflags!( + /// Extra flags - Supported by Linux 2.6.27, normalized on other platforms pub struct SockFlag: c_int { const SOCK_NONBLOCK = 0o0004000; const SOCK_CLOEXEC = 0o2000000; } ); +libc_bitflags!{ + /// Flags for send/recv and their relatives + pub flags MsgFlags: libc::c_int { + /// Sends or requests out-of-band data on sockets that support this notion + /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also + /// support out-of-band data. + MSG_OOB, + /// Peeks at an incoming message. The data is treated as unread and the next + /// [`recv()`](fn.recv.html) + /// or similar function shall still return this data. + MSG_PEEK, + /// Enables nonblocking operation; if the operation would block, + /// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar + /// behavior to setting the `O_NONBLOCK` flag + /// (via the [`fcntl`](../../fcntl/fn.fcntl.html) + /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per- + /// call option, whereas `O_NONBLOCK` is a setting on the open file + /// description (see [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)), + /// which will affect all threads in + /// the calling process and as well as other processes that hold + /// file descriptors referring to the same open file description. + MSG_DONTWAIT, + /// Receive flags: Control Data was discarded (buffer too small) + MSG_CTRUNC, + /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram + /// (since Linux 2.4.27/2.6.8), + /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4) + /// sockets: return the real length of the packet or datagram, even + /// when it was longer than the passed buffer. Not implemented for UNIX + /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets. + /// + /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp). + MSG_TRUNC, + /// Terminates a record (when this notion is supported, as for + /// sockets of type [`SeqPacket`](enum.SockType.html)). + MSG_EOR, + /// This flag specifies that queued errors should be received from + /// the socket error queue. (For more details, see + /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom)) + #[cfg(any(target_os = "linux", target_os = "android"))] + MSG_ERRQUEUE, + /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain + /// file descriptor using the `SCM_RIGHTS` operation (described in + /// [unix(7)](https://linux.die.net/man/7/unix)). + /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of + /// [open(2)](https://linux.die.net/man/2/open). + /// + /// Only used in [`recvmsg`](fn.recvmsg.html) function. + #[cfg(any(target_os = "linux", target_os = "android"))] + MSG_CMSG_CLOEXEC, + } +} + /// Copy the in-memory representation of src into the byte slice dst, /// updating the slice to point to the remainder of dst only. Unsafe /// because it exposes all bytes in src, which may be UB if some of them @@ -157,7 +240,7 @@ impl<'a> Iterator for CmsgIterator<'a> { self.0 = &buf[cmsg_align(cmsg_len)..]; match (cmsg.cmsg_level, cmsg.cmsg_type) { - (SOL_SOCKET, SCM_RIGHTS) => unsafe { + (libc::SOL_SOCKET, libc::SCM_RIGHTS) => unsafe { Some(ControlMessage::ScmRights( slice::from_raw_parts( &cmsg.cmsg_data as *const _ as *const _, 1))) @@ -221,8 +304,8 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmRights(fds) => { let cmsg = cmsghdr { cmsg_len: self.len() as type_of_cmsg_len, - cmsg_level: SOL_SOCKET, - cmsg_type: SCM_RIGHTS, + cmsg_level: libc::SOL_SOCKET, + cmsg_type: libc::SCM_RIGHTS, cmsg_data: [], }; copy_bytes(&cmsg, buf); @@ -330,9 +413,20 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<& /// Create an endpoint for communication /// +/// The `protocol` specifies a particular protocol to be used with the +/// socket. Normally only a single protocol exists to support a +/// particular socket type within a given protocol family, in which case +/// protocol can be specified as `None`. However, it is possible that many +/// protocols may exist, in which case a particular protocol must be +/// specified in this manner. +/// /// [Further reading](http://man7.org/linux/man-pages/man2/socket.2.html) -pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_int) -> Result<RawFd> { +pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> { let mut ty = ty as c_int; + let protocol = match protocol.into() { + None => 0, + Some(p) => p as c_int, + }; let feat_atomic = features::socket_atomic_cloexec(); if feat_atomic { @@ -358,9 +452,13 @@ pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_ /// Create a pair of connected sockets /// /// [Further reading](http://man7.org/linux/man-pages/man2/socketpair.2.html) -pub fn socketpair(domain: AddressFamily, ty: SockType, protocol: c_int, +pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T, flags: SockFlag) -> Result<(RawFd, RawFd)> { let mut ty = ty as c_int; + let protocol = match protocol.into() { + None => 0, + Some(p) => p as c_int, + }; let feat_atomic = features::socket_atomic_cloexec(); if feat_atomic { @@ -551,13 +649,13 @@ pub struct ucred { /// [Further reading](http://man7.org/linux/man-pages/man2/setsockopt.2.html) #[repr(i32)] pub enum SockLevel { - Socket = SOL_SOCKET, - Tcp = IPPROTO_TCP, - Ip = IPPROTO_IP, - Ipv6 = IPPROTO_IPV6, - Udp = IPPROTO_UDP, + Socket = libc::SOL_SOCKET, + Tcp = libc::IPPROTO_TCP, + Ip = libc::IPPROTO_IP, + Ipv6 = libc::IPPROTO_IPV6, + Udp = libc::IPPROTO_UDP, #[cfg(any(target_os = "linux", target_os = "android"))] - Netlink = SOL_NETLINK, + Netlink = libc::SOL_NETLINK, } /// Represents a socket option that can be accessed or set. Used as an argument @@ -639,22 +737,22 @@ pub unsafe fn sockaddr_storage_to_addr( } match addr.ss_family as c_int { - consts::AF_INET => { + libc::AF_INET => { assert!(len as usize == mem::size_of::<sockaddr_in>()); let ret = *(addr as *const _ as *const sockaddr_in); Ok(SockAddr::Inet(InetAddr::V4(ret))) } - consts::AF_INET6 => { + libc::AF_INET6 => { assert!(len as usize == mem::size_of::<sockaddr_in6>()); Ok(SockAddr::Inet(InetAddr::V6((*(addr as *const _ as *const sockaddr_in6))))) } - consts::AF_UNIX => { + libc::AF_UNIX => { let sun = *(addr as *const _ as *const sockaddr_un); let pathlen = len - offset_of!(sockaddr_un, sun_path); Ok(SockAddr::Unix(UnixAddr(sun, pathlen))) } #[cfg(any(target_os = "linux", target_os = "android"))] - consts::AF_NETLINK => { + libc::AF_NETLINK => { use libc::sockaddr_nl; Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl)))) } @@ -681,9 +779,9 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { use libc::shutdown; let how = match how { - Shutdown::Read => consts::SHUT_RD, - Shutdown::Write => consts::SHUT_WR, - Shutdown::Both => consts::SHUT_RDWR, + Shutdown::Read => libc::SHUT_RD, + Shutdown::Write => libc::SHUT_WR, + Shutdown::Both => libc::SHUT_RDWR, }; Errno::result(shutdown(df, how)).map(drop) diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 61d85ec3..3c13c539 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -1,9 +1,7 @@ -use super::{ffi, consts, GetSockOpt, SetSockOpt}; +use super::{ffi, GetSockOpt, SetSockOpt}; use {Errno, Result}; use sys::time::TimeVal; -use libc::{c_int, uint8_t, c_void, socklen_t}; -#[cfg(target_os = "linux")] -use libc::sockaddr_in; +use libc::{self, c_int, uint8_t, c_void, socklen_t}; use std::mem; use std::os::unix::io::RawFd; @@ -130,52 +128,49 @@ macro_rules! sockopt_impl { * */ -sockopt_impl!(Both, ReuseAddr, consts::SOL_SOCKET, consts::SO_REUSEADDR, bool); -sockopt_impl!(Both, ReusePort, consts::SOL_SOCKET, consts::SO_REUSEPORT, bool); -sockopt_impl!(Both, TcpNoDelay, consts::IPPROTO_TCP, consts::TCP_NODELAY, bool); -sockopt_impl!(Both, Linger, consts::SOL_SOCKET, consts::SO_LINGER, super::linger); -sockopt_impl!(SetOnly, IpAddMembership, consts::IPPROTO_IP, consts::IP_ADD_MEMBERSHIP, super::ip_mreq); -sockopt_impl!(SetOnly, IpDropMembership, consts::IPPROTO_IP, consts::IP_DROP_MEMBERSHIP, super::ip_mreq); +sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool); +sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool); +sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool); +sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, super::linger); +sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::ip_mreq); +sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::ip_mreq); #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd")))] -sockopt_impl!(SetOnly, Ipv6AddMembership, consts::IPPROTO_IPV6, consts::IPV6_ADD_MEMBERSHIP, super::ipv6_mreq); +sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::ipv6_mreq); #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd")))] -sockopt_impl!(SetOnly, Ipv6DropMembership, consts::IPPROTO_IPV6, consts::IPV6_DROP_MEMBERSHIP, super::ipv6_mreq); +sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::ipv6_mreq); #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd"))] -sockopt_impl!(SetOnly, Ipv6AddMembership, consts::IPPROTO_IPV6, consts::IPV6_JOIN_GROUP, super::ipv6_mreq); +sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::ipv6_mreq); #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd"))] -sockopt_impl!(SetOnly, Ipv6DropMembership, consts::IPPROTO_IPV6, consts::IPV6_LEAVE_GROUP, super::ipv6_mreq); -sockopt_impl!(Both, IpMulticastTtl, consts::IPPROTO_IP, consts::IP_MULTICAST_TTL, u8); -sockopt_impl!(Both, IpMulticastLoop, consts::IPPROTO_IP, consts::IP_MULTICAST_LOOP, bool); -sockopt_impl!(Both, ReceiveTimeout, consts::SOL_SOCKET, consts::SO_RCVTIMEO, TimeVal); -sockopt_impl!(Both, SendTimeout, consts::SOL_SOCKET, consts::SO_SNDTIMEO, TimeVal); -sockopt_impl!(Both, Broadcast, consts::SOL_SOCKET, consts::SO_BROADCAST, bool); -sockopt_impl!(Both, OobInline, consts::SOL_SOCKET, consts::SO_OOBINLINE, bool); -sockopt_impl!(GetOnly, SocketError, consts::SOL_SOCKET, consts::SO_ERROR, i32); -sockopt_impl!(Both, KeepAlive, consts::SOL_SOCKET, consts::SO_KEEPALIVE, bool); +sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::ipv6_mreq); +sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8); +sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool); +sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal); +sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal); +sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool); +sockopt_impl!(Both, OobInline, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool); +sockopt_impl!(GetOnly, SocketError, libc::SOL_SOCKET, libc::SO_ERROR, i32); +sockopt_impl!(Both, KeepAlive, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool); #[cfg(all(target_os = "linux", not(target_arch="arm")))] -sockopt_impl!(GetOnly, PeerCredentials, consts::SOL_SOCKET, consts::SO_PEERCRED, super::ucred); +sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::ucred); #[cfg(any(target_os = "macos", target_os = "ios"))] -sockopt_impl!(Both, TcpKeepAlive, consts::IPPROTO_TCP, consts::TCP_KEEPALIVE, u32); +sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32); #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "linux", target_os = "android", target_os = "nacl"))] -sockopt_impl!(Both, TcpKeepIdle, consts::IPPROTO_TCP, consts::TCP_KEEPIDLE, u32); -sockopt_impl!(Both, RcvBuf, consts::SOL_SOCKET, consts::SO_RCVBUF, usize); -sockopt_impl!(Both, SndBuf, consts::SOL_SOCKET, consts::SO_SNDBUF, usize); -#[cfg(target_os = "linux")] -sockopt_impl!(SetOnly, RcvBufForce, consts::SOL_SOCKET, consts::SO_RCVBUFFORCE, usize); -#[cfg(all(target_os = "linux", not(target_arch="arm")))] -sockopt_impl!(SetOnly, SndBufForce, consts::SOL_SOCKET, consts::SO_SNDBUFFORCE, usize); -sockopt_impl!(GetOnly, SockType, consts::SOL_SOCKET, consts::SO_TYPE, super::SockType); -#[cfg(any(target_os = "freebsd", - target_os = "linux", - target_os = "nacl"))] -sockopt_impl!(GetOnly, AcceptConn, consts::SOL_SOCKET, consts::SO_ACCEPTCONN, bool); -#[cfg(target_os = "linux")] -sockopt_impl!(GetOnly, OriginalDst, consts::SOL_IP, consts::SO_ORIGINAL_DST, sockaddr_in); +sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32); +sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize); +sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize); +#[cfg(any(target_os = "linux", target_os = "android"))] +sockopt_impl!(SetOnly, RcvBufForce, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize); +#[cfg(any(target_os = "linux", target_os = "android"))] +sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize); +sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType); +sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool); +#[cfg(any(target_os = "linux", target_os = "android"))] +sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in); /* * @@ -383,7 +378,7 @@ mod test { fn can_get_peercred_on_unix_socket() { use super::super::*; - let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap(); + let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap(); let a_cred = getsockopt(a, super::PeerCredentials).unwrap(); let b_cred = getsockopt(b, super::PeerCredentials).unwrap(); assert_eq!(a_cred, b_cred); @@ -395,7 +390,7 @@ mod test { use super::super::*; use ::unistd::close; - let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap(); + let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap(); let a_type = getsockopt(a, super::SockType).unwrap(); assert!(a_type == SockType::Stream); close(a).unwrap(); @@ -407,7 +402,7 @@ mod test { use super::super::*; use ::unistd::close; - let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), 0).unwrap(); + let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap(); let s_type = getsockopt(s, super::SockType).unwrap(); assert!(s_type == SockType::Datagram); close(s).unwrap(); @@ -421,7 +416,7 @@ mod test { use super::super::*; use ::unistd::close; - let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), 0).unwrap(); + let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap(); let s_listening = getsockopt(s, super::AcceptConn).unwrap(); assert!(!s_listening); listen(s, 10).unwrap(); |