Skip to main content

netlink_packet_wireguard/
message.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, Emitable, ErrorContext, NlasIterator, Parseable,
5    ParseableParametrized,
6};
7use netlink_packet_generic::{GenlFamily, GenlHeader};
8
9use crate::WireguardAttribute;
10
11const WG_CMD_GET_DEVICE: u8 = 0;
12const WG_CMD_SET_DEVICE: u8 = 1;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15#[non_exhaustive]
16pub enum WireguardCmd {
17    GetDevice,
18    SetDevice,
19    Other(u8),
20}
21
22impl From<WireguardCmd> for u8 {
23    fn from(cmd: WireguardCmd) -> Self {
24        match cmd {
25            WireguardCmd::GetDevice => WG_CMD_GET_DEVICE,
26            WireguardCmd::SetDevice => WG_CMD_SET_DEVICE,
27            WireguardCmd::Other(d) => d,
28        }
29    }
30}
31
32impl From<u8> for WireguardCmd {
33    fn from(value: u8) -> Self {
34        match value {
35            WG_CMD_GET_DEVICE => Self::GetDevice,
36            WG_CMD_SET_DEVICE => Self::SetDevice,
37            cmd => Self::Other(cmd),
38        }
39    }
40}
41
42#[derive(Clone, Debug, PartialEq, Eq)]
43pub struct WireguardMessage {
44    pub cmd: WireguardCmd,
45    pub attributes: Vec<WireguardAttribute>,
46}
47
48impl GenlFamily for WireguardMessage {
49    fn family_name() -> &'static str {
50        "wireguard"
51    }
52
53    fn version(&self) -> u8 {
54        1
55    }
56
57    fn command(&self) -> u8 {
58        self.cmd.into()
59    }
60}
61
62impl Emitable for WireguardMessage {
63    fn emit(&self, buffer: &mut [u8]) {
64        self.attributes.as_slice().emit(buffer)
65    }
66
67    fn buffer_len(&self) -> usize {
68        self.attributes.as_slice().buffer_len()
69    }
70}
71
72impl ParseableParametrized<[u8], GenlHeader> for WireguardMessage {
73    fn parse_with_param(
74        buf: &[u8],
75        header: GenlHeader,
76    ) -> Result<Self, DecodeError> {
77        Ok(Self {
78            cmd: header.cmd.into(),
79            attributes: parse_attributes(buf)?,
80        })
81    }
82}
83
84fn parse_attributes(
85    buf: &[u8],
86) -> Result<Vec<WireguardAttribute>, DecodeError> {
87    let mut attributes = Vec::new();
88    let error_msg = "failed to parse wireguard netlink attributes";
89    for nla in NlasIterator::new(buf) {
90        let nla = &nla.context(error_msg)?;
91        let parsed = WireguardAttribute::parse(nla)?;
92        attributes.push(parsed);
93    }
94    Ok(attributes)
95}