netlink_packet_wireguard/
attribute.rs1use std::convert::TryInto;
4
5use netlink_packet_core::{
6 emit_u16, emit_u32, parse_string, parse_u16, parse_u32, DecodeError,
7 DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
8 NLA_F_NESTED,
9};
10
11use super::peer::WireguardPeers;
12use crate::WireguardPeer;
13
14const WG_KEY_LEN: usize = 32;
15
16const WGDEVICE_A_IFINDEX: u16 = 1;
17const WGDEVICE_A_IFNAME: u16 = 2;
18const WGDEVICE_A_PRIVATE_KEY: u16 = 3;
19const WGDEVICE_A_PUBLIC_KEY: u16 = 4;
20const WGDEVICE_A_FLAGS: u16 = 5;
21const WGDEVICE_A_LISTEN_PORT: u16 = 6;
22const WGDEVICE_A_FWMARK: u16 = 7;
23const WGDEVICE_A_PEERS: u16 = 8;
24
25#[derive(Clone, Debug, PartialEq, Eq)]
26#[non_exhaustive]
27pub enum WireguardAttribute {
28 IfIndex(u32),
29 IfName(String),
30 PrivateKey([u8; WG_KEY_LEN]),
31 PublicKey([u8; WG_KEY_LEN]),
32 ListenPort(u16),
33 Fwmark(u32),
34 Peers(Vec<WireguardPeer>),
35 Flags(u32),
36 Other(DefaultNla),
37}
38
39impl WireguardAttribute {
40 pub const WG_KEY_LEN: usize = WG_KEY_LEN;
41}
42
43impl Nla for WireguardAttribute {
44 fn value_len(&self) -> usize {
45 match self {
46 Self::IfName(v) => v.len() + 1,
47 Self::PrivateKey(_) | Self::PublicKey(_) => WG_KEY_LEN,
48 Self::ListenPort(_) => 2,
49 Self::Peers(v) => v.as_slice().buffer_len(),
50 Self::Fwmark(_) | Self::IfIndex(_) | Self::Flags(_) => 4,
51 Self::Other(v) => v.value_len(),
52 }
53 }
54
55 fn kind(&self) -> u16 {
56 match self {
57 Self::IfIndex(_) => WGDEVICE_A_IFINDEX,
58 Self::IfName(_) => WGDEVICE_A_IFNAME,
59 Self::PrivateKey(_) => WGDEVICE_A_PRIVATE_KEY,
60 Self::PublicKey(_) => WGDEVICE_A_PUBLIC_KEY,
61 Self::ListenPort(_) => WGDEVICE_A_LISTEN_PORT,
62 Self::Fwmark(_) => WGDEVICE_A_FWMARK,
63 Self::Peers(_) => WGDEVICE_A_PEERS | NLA_F_NESTED,
64 Self::Flags(_) => WGDEVICE_A_FLAGS,
65 Self::Other(attr) => attr.kind(),
66 }
67 }
68
69 fn emit_value(&self, buffer: &mut [u8]) {
70 match self {
71 Self::IfIndex(v) => emit_u32(buffer, *v).unwrap(),
72 Self::IfName(s) => {
73 buffer[..s.len()].copy_from_slice(s.as_bytes());
74 buffer[s.len()] = 0;
75 }
76 Self::PrivateKey(v) => buffer.copy_from_slice(v),
77 Self::PublicKey(v) => buffer.copy_from_slice(v),
78 Self::ListenPort(v) => emit_u16(buffer, *v).unwrap(),
79 Self::Fwmark(v) => emit_u32(buffer, *v).unwrap(),
80 Self::Peers(v) => v.as_slice().emit(buffer),
81 Self::Flags(v) => emit_u32(buffer, *v).unwrap(),
82 Self::Other(attr) => attr.emit_value(buffer),
83 }
84 }
85}
86
87impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
88 for WireguardAttribute
89{
90 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
91 let payload = buf.value();
92 Ok(match buf.kind() {
93 WGDEVICE_A_IFINDEX => Self::IfIndex(
94 parse_u32(payload)
95 .context("invalid WGDEVICE_A_IFINDEX value")?,
96 ),
97 WGDEVICE_A_IFNAME => Self::IfName(
98 parse_string(payload)
99 .context("invalid WGDEVICE_A_IFNAME value")?,
100 ),
101 WGDEVICE_A_PRIVATE_KEY => Self::PrivateKey(
102 payload
103 .try_into()
104 .map_err(|e: std::array::TryFromSliceError| {
105 DecodeError::from(e.to_string())
106 })
107 .context("invalid WGDEVICE_A_PRIVATE_KEY value")?,
108 ),
109 WGDEVICE_A_PUBLIC_KEY => Self::PublicKey(
110 payload
111 .try_into()
112 .map_err(|e: std::array::TryFromSliceError| {
113 DecodeError::from(e.to_string())
114 })
115 .context("invalid WGDEVICE_A_PUBLIC_KEY value")?,
116 ),
117 WGDEVICE_A_LISTEN_PORT => Self::ListenPort(
118 parse_u16(payload)
119 .context("invalid WGDEVICE_A_LISTEN_PORT value")?,
120 ),
121 WGDEVICE_A_FWMARK => Self::Fwmark(
122 parse_u32(payload)
123 .context("invalid WGDEVICE_A_FWMARK value")?,
124 ),
125 WGDEVICE_A_PEERS => Self::Peers(WireguardPeers::parse(buf)?.0),
126 WGDEVICE_A_FLAGS => Self::Flags(
127 parse_u32(payload).context("invalid WGDEVICE_A_FLAGS value")?,
128 ),
129 kind => Self::Other(
130 DefaultNla::parse(buf)
131 .context(format!("unknown NLA type {kind}"))?,
132 ),
133 })
134 }
135}