diff options
Diffstat (limited to 'src/sys/socket')
-rw-r--r-- | src/sys/socket/addr.rs | 51 | ||||
-rw-r--r-- | src/sys/socket/mod.rs | 3 | ||||
-rw-r--r-- | src/sys/socket/sockopt.rs | 3 |
3 files changed, 54 insertions, 3 deletions
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 29832b37..b479c9cd 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -1,5 +1,6 @@ use super::sa_family_t; -use {Errno, Error, Result, NixPath}; +use {Error, Result, NixPath}; +use errno::Errno; use libc; use std::{fmt, hash, mem, net, ptr, slice}; use std::ffi::OsStr; @@ -201,6 +202,26 @@ pub enum AddressFamily { Natm = libc::AF_NATM, } +impl AddressFamily { + /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from + /// the `sa_family` field of a `sockaddr`. + /// + /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink + /// and System. Returns None for unsupported or unknown address families. + pub fn from_i32(family: i32) -> Option<AddressFamily> { + match family { + libc::AF_UNIX => Some(AddressFamily::Unix), + libc::AF_INET => Some(AddressFamily::Inet), + libc::AF_INET6 => Some(AddressFamily::Inet6), + #[cfg(any(target_os = "android", target_os = "linux"))] + libc::AF_NETLINK => Some(AddressFamily::Netlink), + #[cfg(any(target_os = "macos", target_os = "macos"))] + libc::AF_SYSTEM => Some(AddressFamily::System), + _ => None + } + } +} + #[derive(Copy)] pub enum InetAddr { V4(libc::sockaddr_in), @@ -707,6 +728,34 @@ impl SockAddr { format!("{}", self) } + /// Creates a `SockAddr` struct from libc's sockaddr. + /// + /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System. + /// Returns None for unsupported families. + pub unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> { + if addr.is_null() { + None + } else { + match AddressFamily::from_i32((*addr).sa_family as i32) { + Some(AddressFamily::Unix) => None, + Some(AddressFamily::Inet) => Some(SockAddr::Inet( + InetAddr::V4(*(addr as *const libc::sockaddr_in)))), + Some(AddressFamily::Inet6) => Some(SockAddr::Inet( + InetAddr::V6(*(addr as *const libc::sockaddr_in6)))), + #[cfg(any(target_os = "android", target_os = "linux"))] + Some(AddressFamily::Netlink) => Some(SockAddr::Netlink( + NetlinkAddr(*(addr as *const libc::sockaddr_nl)))), + #[cfg(any(target_os = "ios", target_os = "macos"))] + Some(AddressFamily::System) => Some(SockAddr::SysControl( + SysControlAddr(*(addr as *const sys_control::sockaddr_ctl)))), + // Other address families are currently not supported and simply yield a None + // entry instead of a proper conversion to a `SockAddr`. + Some(_) => None, + None => None, + } + } + } + pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) { match *self { SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t), diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index cdb8b4b3..c7d6d581 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1,7 +1,8 @@ //! Socket interface functions //! //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html) -use {Error, Errno, Result}; +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}; diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 98a4eeac..4741ec66 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -1,5 +1,6 @@ use super::{GetSockOpt, SetSockOpt}; -use {Errno, Result}; +use Result; +use errno::Errno; use sys::time::TimeVal; use libc::{self, c_int, uint8_t, c_void, socklen_t}; use std::mem; |