netlink_packet_route/tc/filters/
matchall.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::ErrorContext;
4/// Matchall filter
5///
6/// Matches all packets and performs an action on them.
7use netlink_packet_core::{
8    emit_u32, parse_u32, DecodeError, DefaultNla, Emitable, Nla, NlaBuffer,
9    NlasIterator, Parseable,
10};
11
12use crate::tc::{TcAction, TcHandle};
13
14const TCA_MATCHALL_CLASSID: u16 = 1;
15const TCA_MATCHALL_ACT: u16 = 2;
16const TCA_MATCHALL_FLAGS: u16 = 3;
17const TCA_MATCHALL_PCNT: u16 = 4;
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20#[non_exhaustive]
21pub struct TcFilterMatchAll {}
22impl TcFilterMatchAll {
23    pub const KIND: &'static str = "matchall";
24}
25
26#[derive(Debug, PartialEq, Eq, Clone)]
27#[non_exhaustive]
28pub enum TcFilterMatchAllOption {
29    ClassId(TcHandle),
30    Action(Vec<TcAction>),
31    Pnct(Vec<u8>),
32    Flags(u32),
33    Other(DefaultNla),
34}
35
36impl Nla for TcFilterMatchAllOption {
37    fn value_len(&self) -> usize {
38        match self {
39            Self::Pnct(b) => b.len(),
40            Self::ClassId(_) => 4,
41            Self::Flags(_) => 4,
42            Self::Action(acts) => acts.as_slice().buffer_len(),
43            Self::Other(attr) => attr.value_len(),
44        }
45    }
46
47    fn emit_value(&self, buffer: &mut [u8]) {
48        match self {
49            Self::Pnct(b) => buffer.copy_from_slice(b.as_slice()),
50            Self::ClassId(i) => emit_u32(buffer, (*i).into()).unwrap(),
51            Self::Flags(i) => emit_u32(buffer, *i).unwrap(),
52            Self::Action(acts) => acts.as_slice().emit(buffer),
53            Self::Other(attr) => attr.emit_value(buffer),
54        }
55    }
56
57    fn kind(&self) -> u16 {
58        match self {
59            Self::ClassId(_) => TCA_MATCHALL_CLASSID,
60            Self::Action(_) => TCA_MATCHALL_ACT,
61            Self::Pnct(_) => TCA_MATCHALL_PCNT,
62            Self::Flags(_) => TCA_MATCHALL_FLAGS,
63            Self::Other(attr) => attr.kind(),
64        }
65    }
66}
67
68impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
69    for TcFilterMatchAllOption
70{
71    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
72        let payload = buf.value();
73        Ok(match buf.kind() {
74            TCA_MATCHALL_CLASSID => Self::ClassId(
75                parse_u32(payload)
76                    .context("failed to parse TCA_MATCHALL_UNSPEC")?
77                    .into(),
78            ),
79            TCA_MATCHALL_ACT => {
80                let mut acts = vec![];
81                for act in NlasIterator::new(payload) {
82                    let act = act.context("invalid TCA_MATCHALL_ACT")?;
83                    acts.push(
84                        TcAction::parse(&act)
85                            .context("failed to parse TCA_MATCHALL_ACT")?,
86                    );
87                }
88                Self::Action(acts)
89            }
90            TCA_MATCHALL_PCNT => Self::Pnct(payload.to_vec()),
91            TCA_MATCHALL_FLAGS => Self::Flags(
92                parse_u32(payload)
93                    .context("failed to parse TCA_MATCHALL_FLAGS")?,
94            ),
95            _ => Self::Other(
96                DefaultNla::parse(buf).context("failed to parse u32 nla")?,
97            ),
98        })
99    }
100}