Skip to main content

netlink_bindings/
primitives.rs

1use std::io::Write;
2pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
3
4macro_rules! gen_parse {
5    ($name:ident => $from:ident, $type:ident) => {
6        pub fn $name(buf: &[u8]) -> Option<$type> {
7            if buf.len() != size_of::<$type>() {
8                return None;
9            }
10            Some($type::$from(buf.try_into().unwrap()))
11        }
12    };
13    ($($name:ident => $from:ident, $type:ident;)+) => {
14        $(gen_parse!($name => $from, $type);)+
15    }
16}
17
18gen_parse! {
19    parse_u8      => from_ne_bytes, u8;
20    parse_u16     => from_ne_bytes, u16;
21    parse_u32     => from_ne_bytes, u32;
22    parse_u64     => from_ne_bytes, u64;
23    parse_u128    => from_ne_bytes, u128;
24
25    parse_be_u8   => from_be_bytes, u8;
26    parse_be_u16  => from_be_bytes, u16;
27    parse_be_u32  => from_be_bytes, u32;
28    parse_be_u64  => from_be_bytes, u64;
29    parse_be_u128 => from_be_bytes, u128;
30
31    parse_le_u8   => from_le_bytes, u8;
32    parse_le_u16  => from_le_bytes, u16;
33    parse_le_u32  => from_le_bytes, u32;
34    parse_le_u64  => from_le_bytes, u64;
35    parse_le_u128 => from_le_bytes, u128;
36
37    parse_i8      => from_ne_bytes, i8;
38    parse_i16     => from_ne_bytes, i16;
39    parse_i32     => from_ne_bytes, i32;
40    parse_i64     => from_ne_bytes, i64;
41    parse_i128    => from_ne_bytes, i128;
42
43    parse_be_i8   => from_be_bytes, i8;
44    parse_be_i16  => from_be_bytes, i16;
45    parse_be_i32  => from_be_bytes, i32;
46    parse_be_i64  => from_be_bytes, i64;
47    parse_be_i128 => from_be_bytes, i128;
48
49    parse_le_i8   => from_le_bytes, i8;
50    parse_le_i16  => from_le_bytes, i16;
51    parse_le_i32  => from_le_bytes, i32;
52    parse_le_i64  => from_le_bytes, i64;
53    parse_le_i128 => from_le_bytes, i128;
54}
55
56pub fn parse_ipv4(buf: &[u8]) -> Option<Ipv4Addr> {
57    // TODO: check family
58    parse_be_u32(buf).map(Ipv4Addr::from_bits)
59}
60
61pub fn parse_ipv6(buf: &[u8]) -> Option<Ipv6Addr> {
62    // TODO: check family
63    parse_be_u128(buf).map(Ipv6Addr::from_bits)
64}
65
66pub fn parse_ip(buf: &[u8]) -> Option<IpAddr> {
67    match buf.len() {
68        4 => Some(IpAddr::V4(parse_ipv4(buf).unwrap())),
69        16 => Some(IpAddr::V6(parse_ipv6(buf).unwrap())),
70        _ => None,
71    }
72}
73
74pub fn parse_sockaddr_v4(buf: &[u8]) -> Option<SocketAddrV4> {
75    // TODO: check family
76    if buf.len() != 16 {
77        return None;
78    }
79    Some(SocketAddrV4::new(
80        Ipv4Addr::from_bits(parse_be_u32(&buf[4..8])?),
81        parse_be_u16(&buf[2..4])?,
82    ))
83}
84
85pub fn parse_sockaddr_v6(buf: &[u8]) -> Option<SocketAddrV6> {
86    // TODO: check family
87    if buf.len() != 28 {
88        return None;
89    }
90    Some(SocketAddrV6::new(
91        Ipv6Addr::from_bits(parse_be_u128(&buf[8..24])?),
92        parse_be_u16(&buf[2..4])?,
93        parse_u32(&buf[4..8])?,
94        parse_u32(&buf[24..28])?,
95    ))
96}
97
98pub fn parse_sockaddr(buf: &[u8]) -> Option<SocketAddr> {
99    match buf.len() {
100        16 => Some(SocketAddr::V4(parse_sockaddr_v4(buf).unwrap())),
101        28 => Some(SocketAddr::V6(parse_sockaddr_v6(buf).unwrap())),
102        _ => None,
103    }
104}
105
106pub fn encode_ipv4<W: Write>(buf: &mut W, val: Ipv4Addr) {
107    buf.write_all(&val.to_bits().to_be_bytes()).unwrap()
108}
109
110pub fn encode_ipv6<W: Write>(buf: &mut W, val: Ipv6Addr) {
111    buf.write_all(&val.to_bits().to_be_bytes()).unwrap()
112}
113
114pub fn encode_ip<W: Write>(buf: &mut W, val: IpAddr) {
115    match val {
116        IpAddr::V4(addr) => encode_ipv4(buf, addr),
117        IpAddr::V6(addr) => encode_ipv6(buf, addr),
118    }
119}
120
121pub fn encode_sockaddr_v4(buf: &mut Vec<u8>, val: SocketAddrV4) {
122    buf.extend(&2u16.to_ne_bytes()); // AF_INET
123    buf.extend(&val.port().to_be_bytes());
124    buf.extend(&val.ip().to_bits().to_be_bytes());
125    buf.extend(std::iter::repeat_n(0u8, 8)); // padding
126}
127
128pub fn encode_sockaddr_v6(buf: &mut Vec<u8>, val: SocketAddrV6) {
129    buf.extend(&10u16.to_ne_bytes()); // AF_INET6
130    buf.extend(&val.port().to_be_bytes());
131    buf.extend(&val.flowinfo().to_ne_bytes());
132    buf.extend(&val.ip().to_bits().to_be_bytes());
133    buf.extend(&val.scope_id().to_ne_bytes());
134}
135
136pub fn encode_sockaddr(buf: &mut Vec<u8>, val: SocketAddr) {
137    match val {
138        SocketAddr::V4(addr) => encode_sockaddr_v4(buf, addr),
139        SocketAddr::V6(addr) => encode_sockaddr_v6(buf, addr),
140    }
141}