netlink_packet_generic/ctrl/
mod.rs

1// SPDX-License-Identifier: MIT
2
3//! Generic netlink controller implementation
4//!
5//! This module provides the definition of the controller packet.
6//! It also serves as an example for creating a generic family.
7
8use self::nlas::*;
9use crate::{constants::*, traits::*, GenlHeader};
10use netlink_packet_core::{
11    DecodeError, Emitable, ErrorContext, NlasIterator, Parseable,
12    ParseableParametrized,
13};
14use std::convert::{TryFrom, TryInto};
15
16/// Netlink attributes for this family
17pub mod nlas;
18
19/// Command code definition of Netlink controller (nlctrl) family
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub enum GenlCtrlCmd {
22    /// Notify from event
23    NewFamily,
24    /// Notify from event
25    DelFamily,
26    /// Request to get family info
27    GetFamily,
28    /// Currently unused
29    NewOps,
30    /// Currently unused
31    DelOps,
32    /// Currently unused
33    GetOps,
34    /// Notify from event
35    NewMcastGrp,
36    /// Notify from event
37    DelMcastGrp,
38    /// Currently unused
39    GetMcastGrp,
40    /// Request to get family policy
41    GetPolicy,
42}
43
44impl From<GenlCtrlCmd> for u8 {
45    fn from(cmd: GenlCtrlCmd) -> u8 {
46        use GenlCtrlCmd::*;
47        match cmd {
48            NewFamily => CTRL_CMD_NEWFAMILY,
49            DelFamily => CTRL_CMD_DELFAMILY,
50            GetFamily => CTRL_CMD_GETFAMILY,
51            NewOps => CTRL_CMD_NEWOPS,
52            DelOps => CTRL_CMD_DELOPS,
53            GetOps => CTRL_CMD_GETOPS,
54            NewMcastGrp => CTRL_CMD_NEWMCAST_GRP,
55            DelMcastGrp => CTRL_CMD_DELMCAST_GRP,
56            GetMcastGrp => CTRL_CMD_GETMCAST_GRP,
57            GetPolicy => CTRL_CMD_GETPOLICY,
58        }
59    }
60}
61
62impl TryFrom<u8> for GenlCtrlCmd {
63    type Error = DecodeError;
64
65    fn try_from(value: u8) -> Result<Self, Self::Error> {
66        use GenlCtrlCmd::*;
67        Ok(match value {
68            CTRL_CMD_NEWFAMILY => NewFamily,
69            CTRL_CMD_DELFAMILY => DelFamily,
70            CTRL_CMD_GETFAMILY => GetFamily,
71            CTRL_CMD_NEWOPS => NewOps,
72            CTRL_CMD_DELOPS => DelOps,
73            CTRL_CMD_GETOPS => GetOps,
74            CTRL_CMD_NEWMCAST_GRP => NewMcastGrp,
75            CTRL_CMD_DELMCAST_GRP => DelMcastGrp,
76            CTRL_CMD_GETMCAST_GRP => GetMcastGrp,
77            CTRL_CMD_GETPOLICY => GetPolicy,
78            cmd => {
79                return Err(DecodeError::from(format!(
80                    "Unknown control command: {cmd}"
81                )))
82            }
83        })
84    }
85}
86
87/// Payload of generic netlink controller
88#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct GenlCtrl {
90    /// Command code of this message
91    pub cmd: GenlCtrlCmd,
92    /// Netlink attributes in this message
93    pub nlas: Vec<GenlCtrlAttrs>,
94}
95
96impl GenlFamily for GenlCtrl {
97    fn family_name() -> &'static str {
98        "nlctrl"
99    }
100
101    fn family_id(&self) -> u16 {
102        GENL_ID_CTRL
103    }
104
105    fn command(&self) -> u8 {
106        self.cmd.into()
107    }
108
109    fn version(&self) -> u8 {
110        2
111    }
112}
113
114impl Emitable for GenlCtrl {
115    fn emit(&self, buffer: &mut [u8]) {
116        self.nlas.as_slice().emit(buffer)
117    }
118
119    fn buffer_len(&self) -> usize {
120        self.nlas.as_slice().buffer_len()
121    }
122}
123
124impl ParseableParametrized<[u8], GenlHeader> for GenlCtrl {
125    fn parse_with_param(
126        buf: &[u8],
127        header: GenlHeader,
128    ) -> Result<Self, DecodeError> {
129        Ok(Self {
130            cmd: header.cmd.try_into()?,
131            nlas: parse_ctrlnlas(buf)?,
132        })
133    }
134}
135
136fn parse_ctrlnlas(buf: &[u8]) -> Result<Vec<GenlCtrlAttrs>, DecodeError> {
137    let nlas = NlasIterator::new(buf)
138        .map(|nla| nla.and_then(|nla| GenlCtrlAttrs::parse(&nla)))
139        .collect::<Result<Vec<_>, _>>()
140        .context("failed to parse control message attributes")?;
141
142    Ok(nlas)
143}