diff options
Diffstat (limited to 'src/sys/socket/mod.rs')
-rw-r--r-- | src/sys/socket/mod.rs | 159 |
1 files changed, 123 insertions, 36 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"); -} |