summaryrefslogtreecommitdiff
path: root/src/sys/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/socket')
-rw-r--r--src/sys/socket/addr.rs51
-rw-r--r--src/sys/socket/mod.rs3
-rw-r--r--src/sys/socket/sockopt.rs3
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;