netlink_rs/socket/
address.rs1use 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}