netlink_packet_generic/ctrl/nlas/
mcast.rs1use crate::constants::*;
4use netlink_packet_core::{
5 emit_u32, parse_string, parse_u32, DecodeError, Emitable, ErrorContext,
6 Nla, NlaBuffer, Parseable,
7};
8use std::{mem::size_of_val, ops::Deref};
9
10pub(crate) struct McastGroupList(Vec<McastGroup>);
11
12impl Deref for McastGroupList {
13 type Target = Vec<McastGroup>;
14
15 fn deref(&self) -> &Self::Target {
16 &self.0
17 }
18}
19
20impl From<&Vec<Vec<McastGrpAttrs>>> for McastGroupList {
21 fn from(groups: &Vec<Vec<McastGrpAttrs>>) -> Self {
22 Self(
23 groups
24 .iter()
25 .cloned()
26 .enumerate()
27 .map(|(index, nlas)| McastGroup {
28 index: index as u16,
29 nlas,
30 })
31 .collect(),
32 )
33 }
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct McastGroup {
38 pub index: u16,
39 pub nlas: Vec<McastGrpAttrs>,
40}
41
42impl Nla for McastGroup {
43 fn value_len(&self) -> usize {
44 self.nlas.as_slice().buffer_len()
45 }
46
47 fn kind(&self) -> u16 {
48 self.index + 1
49 }
50
51 fn emit_value(&self, buffer: &mut [u8]) {
52 self.nlas.as_slice().emit(buffer);
53 }
54}
55
56#[derive(Clone, Debug, PartialEq, Eq)]
57pub enum McastGrpAttrs {
58 Name(String),
59 Id(u32),
60}
61
62impl Nla for McastGrpAttrs {
63 fn value_len(&self) -> usize {
64 use McastGrpAttrs::*;
65 match self {
66 Name(s) => s.len() + 1,
67 Id(v) => size_of_val(v),
68 }
69 }
70
71 fn kind(&self) -> u16 {
72 use McastGrpAttrs::*;
73 match self {
74 Name(_) => CTRL_ATTR_MCAST_GRP_NAME,
75 Id(_) => CTRL_ATTR_MCAST_GRP_ID,
76 }
77 }
78
79 fn emit_value(&self, buffer: &mut [u8]) {
80 use McastGrpAttrs::*;
81 match self {
82 Name(s) => {
83 buffer[..s.len()].copy_from_slice(s.as_bytes());
84 buffer[s.len()] = 0;
85 }
86 Id(v) => emit_u32(buffer, *v).unwrap(),
87 }
88 }
89}
90
91impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
92 for McastGrpAttrs
93{
94 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
95 let payload = buf.value();
96 Ok(match buf.kind() {
97 CTRL_ATTR_MCAST_GRP_NAME => Self::Name(
98 parse_string(payload)
99 .context("invalid CTRL_ATTR_MCAST_GRP_NAME value")?,
100 ),
101 CTRL_ATTR_MCAST_GRP_ID => Self::Id(
102 parse_u32(payload)
103 .context("invalid CTRL_ATTR_MCAST_GRP_ID value")?,
104 ),
105 kind => {
106 return Err(DecodeError::from(format!(
107 "Unknown NLA type: {kind}"
108 )))
109 }
110 })
111 }
112}