Skip to main content

netlink_packet_wireguard/
allowedip.rs

1// SPDX-License-Identifier: MIT
2
3use 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        // linux kernel always set it to 0
58        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}