netlink_rs/socket/
address.rs

1use libc::{AF_NETLINK, sa_family_t, sockaddr, c_ushort};
2
3use std::mem;
4use std::io::{self, ErrorKind};
5
6use socket::{ntohl, htonl};
7
8#[repr(C)]
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10struct sockaddr_nl {
11    pub nl_family: sa_family_t,
12    nl_pad: c_ushort,
13    pub nl_pid: u32,
14    pub nl_groups: u32,
15}
16
17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
18pub struct NetlinkAddr(sockaddr_nl);
19
20impl NetlinkAddr {
21    pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
22        NetlinkAddr(sockaddr_nl {
23            nl_family: AF_NETLINK as sa_family_t,
24            nl_pad: 0,
25            nl_pid: htonl(pid),
26            nl_groups: htonl(groups),
27        })
28    }
29
30    pub fn pid(&self) -> u32 {
31        ntohl(self.0.nl_pid)
32    }
33
34    pub fn groups(&self) -> u32 {
35        ntohl(self.0.nl_groups)
36    }
37
38    pub fn as_sockaddr(&self) -> sockaddr {
39        let sa = self.0;
40        unsafe {
41            *(&sa as *const sockaddr_nl as *const sockaddr)
42        }
43    }
44}
45
46pub fn sockaddr_to_netlinkaddr(sa: &sockaddr) -> io::Result<NetlinkAddr> {
47    match sa.sa_family as i32 {
48        AF_NETLINK => {
49            let snl: &sockaddr_nl = unsafe { mem::transmute(sa) };
50            let pid = ntohl(snl.nl_pid);
51            let groups = ntohl(snl.nl_groups);
52            Ok(NetlinkAddr::new(pid, groups))
53        },
54        _ => {
55            Err(io::Error::new(ErrorKind::InvalidInput, "sockaddr is not Netlink family"))
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use libc::{AF_NETLINK, sa_family_t};
63    use super::*;
64
65    #[test]
66    fn netlink_addr_and_sockaddr() {
67        let nladdr = NetlinkAddr::new(0, 10);
68        let sockaddr = nladdr.as_sockaddr();
69        assert_eq!(sockaddr.sa_family, AF_NETLINK as sa_family_t);
70        let nl2 = sockaddr_to_netlinkaddr(&sockaddr).unwrap();
71        assert_eq!(nladdr.pid(), nl2.pid());
72        assert_eq!(nladdr.groups(), nl2.groups());
73    }
74}