netlink_packet_generic/ctrl/nlas/
mcast.rs

1// SPDX-License-Identifier: MIT
2
3use 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}