diff options
Diffstat (limited to 'src/sys/socket')
-rw-r--r-- | src/sys/socket/mod.rs | 159 | ||||
-rw-r--r-- | src/sys/socket/multicast.rs | 40 | ||||
-rw-r--r-- | src/sys/socket/sockopt.rs | 32 |
3 files changed, 142 insertions, 89 deletions
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index c7d6d581..6292bb02 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -4,15 +4,14 @@ use {Error, Result}; use errno::Errno; use features; -use libc::{self, c_void, c_int, socklen_t, size_t, pid_t, uid_t, gid_t}; -use std::{mem, ptr, slice}; +use libc::{self, c_void, c_int, socklen_t, size_t}; +use std::{fmt, mem, ptr, slice}; use std::os::unix::io::RawFd; use sys::time::TimeVal; use sys::uio::IoVec; mod addr; mod ffi; -mod multicast; pub mod sockopt; /* @@ -34,22 +33,14 @@ pub use self::addr::{ pub use ::sys::socket::addr::netlink::NetlinkAddr; pub use libc::{ - in_addr, - in6_addr, + sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, + sockaddr_storage, sockaddr_un, - sa_family_t, -}; - -pub use self::multicast::{ - ip_mreq, - ipv6_mreq, }; -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)] @@ -77,6 +68,7 @@ pub enum SockType { /// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) /// to specify the protocol to use. #[repr(i32)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SockProtocol { /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html)) Tcp = libc::IPPROTO_TCP, @@ -174,6 +166,121 @@ libc_bitflags!{ } } +cfg_if! { + if #[cfg(all(target_os = "linux", not(target_arch = "arm")))] { + /// Unix credentials of the sending process. + /// + /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct UnixCredentials(libc::ucred); + + impl UnixCredentials { + /// Returns the process identifier + pub fn pid(&self) -> libc::pid_t { + self.0.pid + } + + /// Returns the user identifier + pub fn uid(&self) -> libc::uid_t { + self.0.uid + } + + /// Returns the group identifier + pub fn gid(&self) -> libc::gid_t { + self.0.gid + } + } + + impl PartialEq for UnixCredentials { + fn eq(&self, other: &Self) -> bool { + self.0.pid == other.0.pid && self.0.uid == other.0.uid && self.0.gid == other.0.gid + } + } + impl Eq for UnixCredentials {} + + impl fmt::Debug for UnixCredentials { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("UnixCredentials") + .field("pid", &self.0.pid) + .field("uid", &self.0.uid) + .field("gid", &self.0.gid) + .finish() + } + } + } +} + +/// Request for multicast socket operations +/// +/// This is a wrapper type around `ip_mreq`. +#[repr(C)] +#[derive(Clone, Copy)] +pub struct IpMembershipRequest(libc::ip_mreq); + +impl IpMembershipRequest { + /// Instantiate a new `IpMembershipRequest` + /// + /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface. + pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self { + IpMembershipRequest(libc::ip_mreq { + imr_multiaddr: group.0, + imr_interface: interface.unwrap_or(Ipv4Addr::any()).0, + }) + } +} + +impl PartialEq for IpMembershipRequest { + fn eq(&self, other: &Self) -> bool { + self.0.imr_multiaddr.s_addr == other.0.imr_multiaddr.s_addr + && self.0.imr_interface.s_addr == other.0.imr_interface.s_addr + } +} +impl Eq for IpMembershipRequest {} + +impl fmt::Debug for IpMembershipRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("IpMembershipRequest") + .field("imr_multiaddr", &self.0.imr_multiaddr.s_addr) + .field("imr_interface", &self.0.imr_interface.s_addr) + .finish() + } +} + +/// Request for ipv6 multicast socket operations +/// +/// This is a wrapper type around `ipv6_mreq`. +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Ipv6MembershipRequest(libc::ipv6_mreq); + +impl Ipv6MembershipRequest { + /// Instantiate a new `Ipv6MembershipRequest` + pub fn new(group: Ipv6Addr) -> Self { + Ipv6MembershipRequest(libc::ipv6_mreq { + ipv6mr_multiaddr: group.0, + ipv6mr_interface: 0, + }) + } +} + +impl PartialEq for Ipv6MembershipRequest { + fn eq(&self, other: &Self) -> bool { + self.0.ipv6mr_multiaddr.s6_addr == other.0.ipv6mr_multiaddr.s6_addr && + self.0.ipv6mr_interface == other.0.ipv6mr_interface + } +} +impl Eq for Ipv6MembershipRequest {} + +impl fmt::Debug for Ipv6MembershipRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Ipv6MembershipRequest") + .field("ipv6mr_multiaddr", &self.0.ipv6mr_multiaddr.s6_addr) + .field("ipv6mr_interface", &self.0.ipv6mr_interface) + .finish() + } +} + /// 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 @@ -799,21 +906,6 @@ pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> { Errno::result(ret).map(|r| r as usize) } -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct linger { - pub l_onoff: c_int, - pub l_linger: c_int -} - -#[repr(C)] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ucred { - pid: pid_t, - uid: uid_t, - gid: gid_t, -} - /* * * ===== Socket Options ===== @@ -825,13 +917,14 @@ pub struct ucred { /// /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html) #[repr(i32)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SockLevel { 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"))] + #[cfg(any(target_os = "android", target_os = "linux"))] Netlink = libc::SOL_NETLINK, } @@ -938,7 +1031,7 @@ pub unsafe fn sockaddr_storage_to_addr( } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum Shutdown { /// Further receptions will be disallowed. Read, @@ -964,9 +1057,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { Errno::result(shutdown(df, how)).map(drop) } } - -#[test] -pub fn test_struct_sizes() { - use nixtest; - nixtest::assert_size_of::<sockaddr_storage>("sockaddr_storage"); -} diff --git a/src/sys/socket/multicast.rs b/src/sys/socket/multicast.rs deleted file mode 100644 index 7561bb35..00000000 --- a/src/sys/socket/multicast.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::addr::{Ipv4Addr, Ipv6Addr}; -use libc::{in_addr, in6_addr, c_uint}; -use std::fmt; - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct ip_mreq { - pub imr_multiaddr: in_addr, - pub imr_interface: in_addr, -} - -impl fmt::Debug for ip_mreq { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "ip_mreq {{ imr_multiaddr: {{ s_addr: 0x{:x} }}, imr_interface: {{ s_addr: 0x{:x} }} }}", - self.imr_multiaddr.s_addr, self.imr_interface.s_addr) - } -} - -impl ip_mreq { - pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> ip_mreq { - ip_mreq { - imr_multiaddr: group.0, - imr_interface: interface.unwrap_or(Ipv4Addr::any()).0 - } - } -} - -pub struct ipv6_mreq { - pub ipv6mr_multiaddr: in6_addr, - pub ipv6mr_interface: c_uint, -} - -impl ipv6_mreq { - pub fn new(group: Ipv6Addr) -> ipv6_mreq { - ipv6_mreq { - ipv6mr_multiaddr: group.0, - ipv6mr_interface: 0, - } - } -} diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 4741ec66..065d3101 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -132,17 +132,23 @@ macro_rules! sockopt_impl { 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, 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, 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, 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, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::ipv6_mreq); +sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger); +sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::IpMembershipRequest); +sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::IpMembershipRequest); +cfg_if! { + if #[cfg(any(target_os = "android", target_os = "linux"))] { + sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest); + sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest); + } else if #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] { + sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest); + sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest); + } +} 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); @@ -152,7 +158,7 @@ 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, libc::SOL_SOCKET, libc::SO_PEERCRED, super::ucred); +sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials); #[cfg(any(target_os = "macos", target_os = "ios"))] sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32); @@ -384,7 +390,7 @@ mod test { let a_cred = getsockopt(a, super::PeerCredentials).unwrap(); let b_cred = getsockopt(b, super::PeerCredentials).unwrap(); assert_eq!(a_cred, b_cred); - assert!(a_cred.pid != 0); + assert!(a_cred.pid() != 0); } #[test] |