netlink_packet_generic/ctrl/
mod.rs1use self::nlas::*;
9use crate::constants::*;
10use crate::traits::*;
11use crate::GenlHeader;
12use anyhow::Context;
13use netlink_packet_utils::nla::NlasIterator;
14use netlink_packet_utils::traits::*;
15use netlink_packet_utils::DecodeError;
16use std::convert::{TryFrom, TryInto};
17
18pub mod nlas;
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum GenlCtrlCmd {
24 NewFamily,
26 DelFamily,
28 GetFamily,
30 NewOps,
32 DelOps,
34 GetOps,
36 NewMcastGrp,
38 DelMcastGrp,
40 GetMcastGrp,
42 GetPolicy,
44}
45
46impl From<GenlCtrlCmd> for u8 {
47 fn from(cmd: GenlCtrlCmd) -> u8 {
48 use GenlCtrlCmd::*;
49 match cmd {
50 NewFamily => CTRL_CMD_NEWFAMILY,
51 DelFamily => CTRL_CMD_DELFAMILY,
52 GetFamily => CTRL_CMD_GETFAMILY,
53 NewOps => CTRL_CMD_NEWOPS,
54 DelOps => CTRL_CMD_DELOPS,
55 GetOps => CTRL_CMD_GETOPS,
56 NewMcastGrp => CTRL_CMD_NEWMCAST_GRP,
57 DelMcastGrp => CTRL_CMD_DELMCAST_GRP,
58 GetMcastGrp => CTRL_CMD_GETMCAST_GRP,
59 GetPolicy => CTRL_CMD_GETPOLICY,
60 }
61 }
62}
63
64impl TryFrom<u8> for GenlCtrlCmd {
65 type Error = DecodeError;
66
67 fn try_from(value: u8) -> Result<Self, Self::Error> {
68 use GenlCtrlCmd::*;
69 Ok(match value {
70 CTRL_CMD_NEWFAMILY => NewFamily,
71 CTRL_CMD_DELFAMILY => DelFamily,
72 CTRL_CMD_GETFAMILY => GetFamily,
73 CTRL_CMD_NEWOPS => NewOps,
74 CTRL_CMD_DELOPS => DelOps,
75 CTRL_CMD_GETOPS => GetOps,
76 CTRL_CMD_NEWMCAST_GRP => NewMcastGrp,
77 CTRL_CMD_DELMCAST_GRP => DelMcastGrp,
78 CTRL_CMD_GETMCAST_GRP => GetMcastGrp,
79 CTRL_CMD_GETPOLICY => GetPolicy,
80 cmd => return Err(DecodeError::from(format!("Unknown control command: {cmd}"))),
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 type Error = DecodeError;
124 fn parse_with_param(buf: &[u8], header: GenlHeader) -> Result<Self, DecodeError> {
125 Ok(Self { cmd: header.cmd.try_into()?, nlas: parse_ctrlnlas(buf)? })
126 }
127}
128
129fn parse_ctrlnlas(buf: &[u8]) -> Result<Vec<GenlCtrlAttrs>, DecodeError> {
130 let nlas = NlasIterator::new(buf)
131 .map(|nla| {
132 nla.map_err(|err| DecodeError::Nla(err)).and_then(|nla| GenlCtrlAttrs::parse(&nla))
133 })
134 .collect::<Result<Vec<_>, _>>()
135 .context("failed to parse control message attributes")?;
136
137 Ok(nlas)
138}