From 9eccfc2bd84ebab6a3742e4b408097a8ca1f0ead Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Sun, 8 Nov 2015 03:22:33 +0300 Subject: Netlink bits --- src/sys/socket/addr.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) (limited to 'src/sys/socket/addr.rs') 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::() as libc::socklen_t), SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::() as libc::socklen_t), SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + mem::size_of::()) as libc::socklen_t), +#[cfg(any(target_os = "linux", target_os = "android"))] + SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::() 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(&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()) } } } -- cgit v1.2.3