netlink_packet_generic/ctrl/
mod.rs1use 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
16pub mod nlas;
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub enum GenlCtrlCmd {
22 NewFamily,
24 DelFamily,
26 GetFamily,
28 NewOps,
30 DelOps,
32 GetOps,
34 NewMcastGrp,
36 DelMcastGrp,
38 GetMcastGrp,
40 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#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct GenlCtrl {
90 pub cmd: GenlCtrlCmd,
92 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}