netlink_packet_generic/ctrl/
mod.rs1use self::nlas::*;
9use crate::{constants::*, traits::*, GenlHeader};
10use anyhow::Context;
11use netlink_packet_utils::{nla::NlasIterator, traits::*, DecodeError};
12use std::convert::{TryFrom, TryInto};
13
14pub mod nlas;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub enum GenlCtrlCmd {
20 NewFamily,
22 DelFamily,
24 GetFamily,
26 NewOps,
28 DelOps,
30 GetOps,
32 NewMcastGrp,
34 DelMcastGrp,
36 GetMcastGrp,
38 GetPolicy,
40}
41
42impl From<GenlCtrlCmd> for u8 {
43 fn from(cmd: GenlCtrlCmd) -> u8 {
44 use GenlCtrlCmd::*;
45 match cmd {
46 NewFamily => CTRL_CMD_NEWFAMILY,
47 DelFamily => CTRL_CMD_DELFAMILY,
48 GetFamily => CTRL_CMD_GETFAMILY,
49 NewOps => CTRL_CMD_NEWOPS,
50 DelOps => CTRL_CMD_DELOPS,
51 GetOps => CTRL_CMD_GETOPS,
52 NewMcastGrp => CTRL_CMD_NEWMCAST_GRP,
53 DelMcastGrp => CTRL_CMD_DELMCAST_GRP,
54 GetMcastGrp => CTRL_CMD_GETMCAST_GRP,
55 GetPolicy => CTRL_CMD_GETPOLICY,
56 }
57 }
58}
59
60impl TryFrom<u8> for GenlCtrlCmd {
61 type Error = DecodeError;
62
63 fn try_from(value: u8) -> Result<Self, Self::Error> {
64 use GenlCtrlCmd::*;
65 Ok(match value {
66 CTRL_CMD_NEWFAMILY => NewFamily,
67 CTRL_CMD_DELFAMILY => DelFamily,
68 CTRL_CMD_GETFAMILY => GetFamily,
69 CTRL_CMD_NEWOPS => NewOps,
70 CTRL_CMD_DELOPS => DelOps,
71 CTRL_CMD_GETOPS => GetOps,
72 CTRL_CMD_NEWMCAST_GRP => NewMcastGrp,
73 CTRL_CMD_DELMCAST_GRP => DelMcastGrp,
74 CTRL_CMD_GETMCAST_GRP => GetMcastGrp,
75 CTRL_CMD_GETPOLICY => GetPolicy,
76 cmd => {
77 return Err(DecodeError::from(format!(
78 "Unknown control command: {cmd}"
79 )))
80 }
81 })
82 }
83}
84
85#[derive(Clone, Debug, PartialEq, Eq)]
87pub struct GenlCtrl {
88 pub cmd: GenlCtrlCmd,
90 pub nlas: Vec<GenlCtrlAttrs>,
92}
93
94impl GenlFamily for GenlCtrl {
95 fn family_name() -> &'static str {
96 "nlctrl"
97 }
98
99 fn family_id(&self) -> u16 {
100 GENL_ID_CTRL
101 }
102
103 fn command(&self) -> u8 {
104 self.cmd.into()
105 }
106
107 fn version(&self) -> u8 {
108 2
109 }
110}
111
112impl Emitable for GenlCtrl {
113 fn emit(&self, buffer: &mut [u8]) {
114 self.nlas.as_slice().emit(buffer)
115 }
116
117 fn buffer_len(&self) -> usize {
118 self.nlas.as_slice().buffer_len()
119 }
120}
121
122impl ParseableParametrized<[u8], GenlHeader> for GenlCtrl {
123 fn parse_with_param(
124 buf: &[u8],
125 header: GenlHeader,
126 ) -> Result<Self, DecodeError> {
127 Ok(Self {
128 cmd: header.cmd.try_into()?,
129 nlas: parse_ctrlnlas(buf)?,
130 })
131 }
132}
133
134fn parse_ctrlnlas(buf: &[u8]) -> Result<Vec<GenlCtrlAttrs>, DecodeError> {
135 let nlas = NlasIterator::new(buf)
136 .map(|nla| nla.and_then(|nla| GenlCtrlAttrs::parse(&nla)))
137 .collect::<Result<Vec<_>, _>>()
138 .context("failed to parse control message attributes")?;
139
140 Ok(nlas)
141}