summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sys/socket/addr.rs91
-rw-r--r--src/sys/socket/consts.rs2
-rw-r--r--src/sys/socket/mod.rs5
3 files changed, 97 insertions, 1 deletions
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 343e54f9..30a32610 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -5,6 +5,8 @@ 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"))]
+use ::sys::socket::addr::netlink::NetlinkAddr;
// TODO: uncomment out IpAddr functions: rust-lang/rfcs#988
@@ -14,12 +16,24 @@ use std::os::unix::ffi::OsStrExt;
*
*/
+#[cfg(any(target_os = "linux", target_os = "android"))]
+#[derive(Debug,Copy,Clone)]
+#[repr(C)]
+pub struct sockaddr_nl {
+ pub nl_family: sa_family_t,
+ nl_pad: libc::c_ushort,
+ pub nl_pid: u32,
+ pub nl_groups: u32
+}
+
#[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,
}
#[derive(Copy)]
@@ -449,7 +463,9 @@ impl fmt::Display for UnixAddr {
#[derive(Copy)]
pub enum SockAddr {
Inet(InetAddr),
- Unix(UnixAddr)
+ Unix(UnixAddr),
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ Netlink(NetlinkAddr)
}
impl SockAddr {
@@ -461,11 +477,18 @@ impl SockAddr {
Ok(SockAddr::Unix(try!(UnixAddr::new(path))))
}
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
+ SockAddr::Netlink(NetlinkAddr::new(pid, groups))
+ }
+
pub fn family(&self) -> AddressFamily {
match *self {
SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
SockAddr::Unix(..) => AddressFamily::Unix,
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ SockAddr::Netlink(..) => AddressFamily::Netlink,
}
}
@@ -478,6 +501,8 @@ 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 + mem::size_of::<libc::sa_family_t>()) as libc::socklen_t),
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sockaddr_nl>() as libc::socklen_t),
}
}
}
@@ -491,6 +516,10 @@ impl PartialEq for SockAddr {
(SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => {
a == b
}
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ (SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => {
+ a == b
+ }
_ => false,
}
}
@@ -504,6 +533,8 @@ 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"))]
+ SockAddr::Netlink(ref a) => a.hash(s),
}
}
}
@@ -519,6 +550,64 @@ 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"))]
+ SockAddr::Netlink(ref nl) => nl.fmt(f),
+ }
+ }
+}
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub mod netlink {
+ use ::sys::socket::addr::{AddressFamily,sockaddr_nl};
+ use libc::sa_family_t;
+ use std::{fmt, hash};
+
+ #[derive(Copy)]
+ pub struct NetlinkAddr(pub sockaddr_nl);
+
+ impl NetlinkAddr {
+ pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
+ NetlinkAddr(sockaddr_nl {
+ nl_family: AddressFamily::Netlink as sa_family_t,
+ nl_pad: 0,
+ nl_pid: pid,
+ nl_groups: groups,
+ })
+ }
+
+ pub fn pid(&self) -> u32 {
+ self.0.nl_pid
+ }
+
+ pub fn groups(&self) -> u32 {
+ self.0.nl_groups
+ }
+ }
+
+ impl PartialEq for NetlinkAddr {
+ fn eq(&self, other: &NetlinkAddr) -> bool {
+ self.0.nl_pid == other.0.nl_pid && self.0.nl_groups == self.0.nl_groups
+ }
+ }
+
+ impl Eq for NetlinkAddr {
+ }
+
+ impl hash::Hash for NetlinkAddr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ ( self.0.nl_family, self.0.nl_pid, self.0.nl_groups).hash(s)
+ }
+ }
+
+ impl Clone for NetlinkAddr {
+ fn clone(&self) -> NetlinkAddr {
+ *self
+ }
+ }
+
+ impl fmt::Display for NetlinkAddr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "pid: {} groups: {}", self.pid(), self.groups())
}
}
}
diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs
index 5cb69202..eb1ca4b7 100644
--- a/src/sys/socket/consts.rs
+++ b/src/sys/socket/consts.rs
@@ -8,6 +8,7 @@ mod os {
pub const AF_LOCAL: c_int = AF_UNIX;
pub const AF_INET: c_int = 2;
pub const AF_INET6: c_int = 10;
+ pub const AF_NETLINK: c_int = 16;
pub const SOCK_STREAM: c_int = 1;
pub const SOCK_DGRAM: c_int = 2;
@@ -20,6 +21,7 @@ mod os {
pub const SOL_TCP: c_int = 6;
pub const SOL_UDP: c_int = 17;
pub const SOL_IPV6: c_int = 41;
+ pub const SOL_NETLINK: c_int = 270;
pub const IPPROTO_IP: c_int = SOL_IP;
pub const IPPROTO_IPV6: c_int = SOL_IPV6;
pub const IPPROTO_TCP: c_int = SOL_TCP;
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index fe88b376..5922f135 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -31,6 +31,9 @@ pub use self::addr::{
Ipv4Addr,
Ipv6Addr,
};
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub use ::sys::socket::addr::netlink::NetlinkAddr;
+
pub use libc::{
in_addr,
in6_addr,
@@ -538,6 +541,8 @@ pub enum SockLevel {
Ip = IPPROTO_IP,
Ipv6 = IPPROTO_IPV6,
Udp = IPPROTO_UDP,
+#[cfg(any(target_os = "linux", target_os = "android"))]
+ Netlink = SOL_NETLINK,
}
/// Represents a socket option that can be accessed or set. Used as an argument