1use crate::constants::*;
4use anyhow::Context;
5use byteorder::{ByteOrder, NativeEndian};
6use netlink_packet_utils::{
7 nla::{Nla, NlaBuffer, NlasIterator},
8 parsers::*,
9 traits::*,
10 DecodeError,
11};
12use std::mem::size_of_val;
13
14mod mcast;
15mod oppolicy;
16mod ops;
17mod policy;
18
19pub use mcast::*;
20pub use oppolicy::*;
21pub use ops::*;
22pub use policy::*;
23
24#[derive(Clone, Debug, PartialEq, Eq)]
25pub enum GenlCtrlAttrs {
26 FamilyId(u16),
27 FamilyName(String),
28 Version(u32),
29 HdrSize(u32),
30 MaxAttr(u32),
31 Ops(Vec<Vec<OpAttrs>>),
32 McastGroups(Vec<Vec<McastGrpAttrs>>),
33 Policy(PolicyAttr),
34 OpPolicy(OppolicyAttr),
35 Op(u32),
36}
37
38impl Nla for GenlCtrlAttrs {
39 fn value_len(&self) -> usize {
40 use GenlCtrlAttrs::*;
41 match self {
42 FamilyId(v) => size_of_val(v),
43 FamilyName(s) => s.len() + 1,
44 Version(v) => size_of_val(v),
45 HdrSize(v) => size_of_val(v),
46 MaxAttr(v) => size_of_val(v),
47 Ops(nlas) => OpList::from(nlas).as_slice().buffer_len(),
48 McastGroups(nlas) => {
49 McastGroupList::from(nlas).as_slice().buffer_len()
50 }
51 Policy(nla) => nla.buffer_len(),
52 OpPolicy(nla) => nla.buffer_len(),
53 Op(v) => size_of_val(v),
54 }
55 }
56
57 fn kind(&self) -> u16 {
58 use GenlCtrlAttrs::*;
59 match self {
60 FamilyId(_) => CTRL_ATTR_FAMILY_ID,
61 FamilyName(_) => CTRL_ATTR_FAMILY_NAME,
62 Version(_) => CTRL_ATTR_VERSION,
63 HdrSize(_) => CTRL_ATTR_HDRSIZE,
64 MaxAttr(_) => CTRL_ATTR_MAXATTR,
65 Ops(_) => CTRL_ATTR_OPS,
66 McastGroups(_) => CTRL_ATTR_MCAST_GROUPS,
67 Policy(_) => CTRL_ATTR_POLICY,
68 OpPolicy(_) => CTRL_ATTR_OP_POLICY,
69 Op(_) => CTRL_ATTR_OP,
70 }
71 }
72
73 fn emit_value(&self, buffer: &mut [u8]) {
74 use GenlCtrlAttrs::*;
75 match self {
76 FamilyId(v) => NativeEndian::write_u16(buffer, *v),
77 FamilyName(s) => {
78 buffer[..s.len()].copy_from_slice(s.as_bytes());
79 buffer[s.len()] = 0;
80 }
81 Version(v) => NativeEndian::write_u32(buffer, *v),
82 HdrSize(v) => NativeEndian::write_u32(buffer, *v),
83 MaxAttr(v) => NativeEndian::write_u32(buffer, *v),
84 Ops(nlas) => {
85 OpList::from(nlas).as_slice().emit(buffer);
86 }
87 McastGroups(nlas) => {
88 McastGroupList::from(nlas).as_slice().emit(buffer);
89 }
90 Policy(nla) => nla.emit_value(buffer),
91 OpPolicy(nla) => nla.emit_value(buffer),
92 Op(v) => NativeEndian::write_u32(buffer, *v),
93 }
94 }
95}
96
97impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
98 for GenlCtrlAttrs
99{
100 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
101 let payload = buf.value();
102 Ok(match buf.kind() {
103 CTRL_ATTR_FAMILY_ID => Self::FamilyId(
104 parse_u16(payload)
105 .context("invalid CTRL_ATTR_FAMILY_ID value")?,
106 ),
107 CTRL_ATTR_FAMILY_NAME => Self::FamilyName(
108 parse_string(payload)
109 .context("invalid CTRL_ATTR_FAMILY_NAME value")?,
110 ),
111 CTRL_ATTR_VERSION => Self::Version(
112 parse_u32(payload)
113 .context("invalid CTRL_ATTR_VERSION value")?,
114 ),
115 CTRL_ATTR_HDRSIZE => Self::HdrSize(
116 parse_u32(payload)
117 .context("invalid CTRL_ATTR_HDRSIZE value")?,
118 ),
119 CTRL_ATTR_MAXATTR => Self::MaxAttr(
120 parse_u32(payload)
121 .context("invalid CTRL_ATTR_MAXATTR value")?,
122 ),
123 CTRL_ATTR_OPS => {
124 let ops = NlasIterator::new(payload)
125 .map(|nlas| {
126 nlas.and_then(|nlas| {
127 NlasIterator::new(nlas.value())
128 .map(|nla| {
129 nla.and_then(|nla| OpAttrs::parse(&nla))
130 })
131 .collect::<Result<Vec<_>, _>>()
132 })
133 })
134 .collect::<Result<Vec<Vec<_>>, _>>()
135 .context("failed to parse CTRL_ATTR_OPS")?;
136 Self::Ops(ops)
137 }
138 CTRL_ATTR_MCAST_GROUPS => {
139 let groups = NlasIterator::new(payload)
140 .map(|nlas| {
141 nlas.and_then(|nlas| {
142 NlasIterator::new(nlas.value())
143 .map(|nla| {
144 nla.and_then(|nla| {
145 McastGrpAttrs::parse(&nla)
146 })
147 })
148 .collect::<Result<Vec<_>, _>>()
149 })
150 })
151 .collect::<Result<Vec<Vec<_>>, _>>()
152 .context("failed to parse CTRL_ATTR_MCAST_GROUPS")?;
153 Self::McastGroups(groups)
154 }
155 CTRL_ATTR_POLICY => Self::Policy(
156 PolicyAttr::parse(&NlaBuffer::new(payload))
157 .context("failed to parse CTRL_ATTR_POLICY")?,
158 ),
159 CTRL_ATTR_OP_POLICY => Self::OpPolicy(
160 OppolicyAttr::parse(&NlaBuffer::new(payload))
161 .context("failed to parse CTRL_ATTR_OP_POLICY")?,
162 ),
163 CTRL_ATTR_OP => Self::Op(parse_u32(payload)?),
164 kind => {
165 return Err(DecodeError::from(format!(
166 "Unknown NLA type: {kind}"
167 )))
168 }
169 })
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn mcast_groups_parse() {
179 let mcast_bytes: [u8; 24] = [
180 24, 0, 7, 0, 20, 0, 1, 0, 8, 0, 2, 0, 1, 0, 0, 0, 8, 0, 1, 0, b't', b'e', b's', b't', ];
191 let nla_buffer = NlaBuffer::new_checked(&mcast_bytes[..])
192 .expect("Failed to create NlaBuffer");
193 let result_attr = GenlCtrlAttrs::parse(&nla_buffer)
194 .expect("Failed to parse encoded McastGroups");
195 let expected_attr = GenlCtrlAttrs::McastGroups(vec![vec![
196 McastGrpAttrs::Id(1),
197 McastGrpAttrs::Name("test".to_string()),
198 ]]);
199 assert_eq!(expected_attr, result_attr);
200 }
201
202 #[test]
203 fn mcast_groups_emit() {
204 let mcast_attr = GenlCtrlAttrs::McastGroups(vec![
205 vec![
206 McastGrpAttrs::Id(7),
207 McastGrpAttrs::Name("group1".to_string()),
208 ],
209 vec![
210 McastGrpAttrs::Id(8),
211 McastGrpAttrs::Name("group2".to_string()),
212 ],
213 ]);
214 let expected_bytes: [u8; 52] = [
215 52, 0, 7, 0, 24, 0, 1, 0, 8, 0, 2, 0, 7, 0, 0, 0, 11, 0, 1, 0, b'g', b'r', b'o', b'u', b'p', b'1', 0, 0, 24, 0, 2, 0, 8, 0, 2, 0, 8, 0, 0, 0, 11, 0, 1, 0, b'g', b'r', b'o', b'u', b'p', b'2', 0, 0, ];
236 let mut buf = vec![0u8; 100];
237 mcast_attr.emit(&mut buf);
238
239 assert_eq!(&expected_bytes[..], &buf[..expected_bytes.len()]);
240 }
241
242 #[test]
243 fn ops_parse() {
244 let ops_bytes: [u8; 24] = [
245 24, 0, 6, 0, 20, 0, 0, 0, 8, 0, 1, 0, 1, 0, 0, 0, 8, 0, 2, 0, 123, 0, 0, 0, ];
256 let nla_buffer = NlaBuffer::new_checked(&ops_bytes[..])
257 .expect("Failed to create NlaBuffer");
258 let result_attr = GenlCtrlAttrs::parse(&nla_buffer)
259 .expect("Failed to parse encoded McastGroups");
260 let expected_attr =
261 GenlCtrlAttrs::Ops(vec![vec![OpAttrs::Id(1), OpAttrs::Flags(123)]]);
262 assert_eq!(expected_attr, result_attr);
263 }
264
265 #[test]
266 fn ops_emit() {
267 let ops = GenlCtrlAttrs::Ops(vec![
268 vec![OpAttrs::Id(1), OpAttrs::Flags(11)],
269 vec![OpAttrs::Id(3), OpAttrs::Flags(33)],
270 ]);
271 let expected_bytes: [u8; 44] = [
272 44, 0, 6, 0, 20, 0, 1, 0, 8, 0, 1, 0, 1, 0, 0, 0, 8, 0, 2, 0, 11, 0, 0, 0, 20, 0, 2, 0, 8, 0, 1, 0, 3, 0, 0, 0, 8, 0, 2, 0, 33, 0, 0, 0, ];
291 let mut buf = vec![0u8; 100];
292 ops.emit(&mut buf);
293
294 assert_eq!(&expected_bytes[..], &buf[..expected_bytes.len()]);
295 }
296}