netlink_packet_generic/ctrl/nlas/
mcast.rs

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