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 +++++++++++++++++++++++++++++++++++++++++++++++- src/sys/socket/consts.rs | 2 ++ src/sys/socket/mod.rs | 5 +++ 3 files changed, 97 insertions(+), 1 deletion(-) 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()) } } } 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 -- cgit v1.2.3