netlink_packet_wireguard/
allowedip.rs1use std::net::IpAddr;
4
5use netlink_packet_core::{
6 emit_u16, parse_ip, parse_u16, DecodeError, DefaultNla, Emitable,
7 ErrorContext, Nla, NlaBuffer, NlasIterator, Parseable, NLA_F_NESTED,
8};
9
10const WGALLOWEDIP_A_FAMILY: u16 = 1;
11const WGALLOWEDIP_A_IPADDR: u16 = 2;
12const WGALLOWEDIP_A_CIDR_MASK: u16 = 3;
13
14pub(crate) struct WireguardAllowedIps(pub(crate) Vec<WireguardAllowedIp>);
15
16impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
17 for WireguardAllowedIps
18{
19 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
20 let mut ret = Vec::new();
21 let nlas = NlasIterator::new(buf.value());
22 for nla in nlas {
23 let nla = nla?;
24 ret.push(WireguardAllowedIp::parse(&nla)?);
25 }
26 Ok(Self(ret))
27 }
28}
29
30impl std::ops::Deref for WireguardAllowedIps {
31 type Target = Vec<WireguardAllowedIp>;
32
33 fn deref(&self) -> &Self::Target {
34 &self.0
35 }
36}
37
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct WireguardAllowedIp(pub Vec<WireguardAllowedIpAttr>);
40
41impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
42 for WireguardAllowedIp
43{
44 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
45 let mut ret = Vec::new();
46 let nlas = NlasIterator::new(buf.value());
47 for nla in nlas {
48 let nla = nla?;
49 ret.push(WireguardAllowedIpAttr::parse(&nla)?);
50 }
51 Ok(Self(ret))
52 }
53}
54
55impl Nla for WireguardAllowedIp {
56 fn kind(&self) -> u16 {
57 NLA_F_NESTED
59 }
60
61 fn value_len(&self) -> usize {
62 self.0.as_slice().buffer_len()
63 }
64
65 fn emit_value(&self, buffer: &mut [u8]) {
66 self.0.as_slice().emit(buffer)
67 }
68}
69
70impl std::ops::Deref for WireguardAllowedIp {
71 type Target = Vec<WireguardAllowedIpAttr>;
72
73 fn deref(&self) -> &Self::Target {
74 &self.0
75 }
76}
77
78const AF_INET6: u16 = 10;
79const AF_INET: u16 = 2;
80
81#[derive(Clone, Copy, Debug, PartialEq, Eq)]
82#[non_exhaustive]
83pub enum WireguardAddressFamily {
84 Ipv4,
85 Ipv6,
86 Other(u16),
87}
88
89impl From<u16> for WireguardAddressFamily {
90 fn from(d: u16) -> Self {
91 match d {
92 AF_INET6 => Self::Ipv6,
93 AF_INET => Self::Ipv4,
94 _ => Self::Other(d),
95 }
96 }
97}
98
99impl From<WireguardAddressFamily> for u16 {
100 fn from(v: WireguardAddressFamily) -> u16 {
101 match v {
102 WireguardAddressFamily::Ipv6 => AF_INET6,
103 WireguardAddressFamily::Ipv4 => AF_INET,
104 WireguardAddressFamily::Other(d) => d,
105 }
106 }
107}
108
109#[derive(Clone, Debug, PartialEq, Eq)]
110#[non_exhaustive]
111pub enum WireguardAllowedIpAttr {
112 Family(WireguardAddressFamily),
113 IpAddr(IpAddr),
114 Cidr(u8),
115 Other(DefaultNla),
116}
117
118impl Nla for WireguardAllowedIpAttr {
119 fn value_len(&self) -> usize {
120 match self {
121 Self::Family(_) => 2,
122 Self::IpAddr(v) => match *v {
123 IpAddr::V4(_) => 4,
124 IpAddr::V6(_) => 16,
125 },
126 Self::Cidr(_) => 1,
127 Self::Other(nla) => nla.value_len(),
128 }
129 }
130
131 fn kind(&self) -> u16 {
132 match self {
133 Self::Family(_) => WGALLOWEDIP_A_FAMILY,
134 Self::IpAddr(_) => WGALLOWEDIP_A_IPADDR,
135 Self::Cidr(_) => WGALLOWEDIP_A_CIDR_MASK,
136 Self::Other(nla) => nla.kind(),
137 }
138 }
139
140 fn emit_value(&self, buffer: &mut [u8]) {
141 match self {
142 Self::Family(v) => emit_u16(buffer, u16::from(*v)).unwrap(),
143 Self::IpAddr(ip) => match ip {
144 IpAddr::V4(ip) => buffer.copy_from_slice(&ip.octets()),
145 IpAddr::V6(ip) => buffer.copy_from_slice(&ip.octets()),
146 },
147 Self::Cidr(v) => buffer[0] = *v,
148 Self::Other(nla) => nla.emit_value(buffer),
149 }
150 }
151}
152
153impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
154 for WireguardAllowedIpAttr
155{
156 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
157 let payload = buf.value();
158 Ok(match buf.kind() {
159 WGALLOWEDIP_A_FAMILY => Self::Family(
160 parse_u16(payload)
161 .context("invalid WGALLOWEDIP_A_FAMILY value")?
162 .into(),
163 ),
164 WGALLOWEDIP_A_IPADDR => Self::IpAddr(
165 parse_ip(payload)
166 .context("invalid WGALLOWEDIP_A_IPADDR value")?,
167 ),
168 WGALLOWEDIP_A_CIDR_MASK => Self::Cidr(payload[0]),
169 kind => Self::Other(
170 DefaultNla::parse(buf)
171 .context(format!("unknown NLA type {kind}"))?,
172 ),
173 })
174 }
175}