rustables/
parser_impls.rs

1use std::{
2    fmt::Debug,
3    mem::{size_of, transmute},
4};
5
6use rustables_macros::nfnetlink_struct;
7
8use crate::{
9    error::DecodeError,
10    expr::Verdict,
11    nlmsg::{
12        pad_netlink_object, pad_netlink_object_with_variable_size, AttributeDecoder,
13        NfNetlinkAttribute, NfNetlinkDeserializable, NfNetlinkObject,
14    },
15    parser::{parse_object, write_attribute},
16    sys::{nlattr, NFTA_DATA_VALUE, NFTA_DATA_VERDICT, NFTA_LIST_ELEM, NLA_TYPE_MASK},
17    ProtocolFamily,
18};
19
20impl NfNetlinkAttribute for u8 {
21    fn write_payload(&self, addr: &mut [u8]) {
22        addr[0] = *self;
23    }
24}
25
26impl NfNetlinkDeserializable for u8 {
27    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
28        Ok((buf[0], &buf[1..]))
29    }
30}
31
32impl NfNetlinkAttribute for u16 {
33    fn write_payload(&self, addr: &mut [u8]) {
34        addr[0..size_of::<Self>()].copy_from_slice(&self.to_be_bytes());
35    }
36}
37
38impl NfNetlinkDeserializable for u16 {
39    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
40        Ok((u16::from_be_bytes([buf[0], buf[1]]), &buf[2..]))
41    }
42}
43
44impl NfNetlinkAttribute for i32 {
45    fn write_payload(&self, addr: &mut [u8]) {
46        addr[0..size_of::<Self>()].copy_from_slice(&self.to_be_bytes());
47    }
48}
49
50impl NfNetlinkDeserializable for i32 {
51    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
52        Ok((
53            i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]),
54            &buf[4..],
55        ))
56    }
57}
58
59impl NfNetlinkAttribute for u32 {
60    fn write_payload(&self, addr: &mut [u8]) {
61        addr[0..size_of::<Self>()].copy_from_slice(&self.to_be_bytes());
62    }
63}
64
65impl NfNetlinkDeserializable for u32 {
66    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
67        Ok((
68            u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]),
69            &buf[4..],
70        ))
71    }
72}
73
74impl NfNetlinkAttribute for u64 {
75    fn write_payload(&self, addr: &mut [u8]) {
76        addr[0..size_of::<Self>()].copy_from_slice(&self.to_be_bytes());
77    }
78}
79
80impl NfNetlinkDeserializable for u64 {
81    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
82        Ok((
83            u64::from_be_bytes([
84                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
85            ]),
86            &buf[8..],
87        ))
88    }
89}
90
91impl NfNetlinkAttribute for String {
92    fn get_size(&self) -> usize {
93        self.len()
94    }
95
96    fn write_payload(&self, addr: &mut [u8]) {
97        addr[0..self.len()].copy_from_slice(&self.as_bytes());
98    }
99}
100
101impl NfNetlinkDeserializable for String {
102    fn deserialize(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
103        // ignore the NULL byte terminator, if any
104        if buf.len() > 0 && buf[buf.len() - 1] == 0 {
105            buf = &buf[..buf.len() - 1];
106        }
107        Ok((String::from_utf8(buf.to_vec())?, &[]))
108    }
109}
110
111impl NfNetlinkAttribute for Vec<u8> {
112    fn get_size(&self) -> usize {
113        self.len()
114    }
115
116    fn write_payload(&self, addr: &mut [u8]) {
117        addr[0..self.len()].copy_from_slice(&self.as_slice());
118    }
119}
120
121impl NfNetlinkDeserializable for Vec<u8> {
122    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
123        Ok((buf.to_vec(), &[]))
124    }
125}
126#[derive(Clone, PartialEq, Eq, Default, Debug)]
127#[nfnetlink_struct(nested = true)]
128pub struct NfNetlinkData {
129    #[field(NFTA_DATA_VALUE)]
130    value: Vec<u8>,
131    #[field(NFTA_DATA_VERDICT)]
132    verdict: Verdict,
133}
134
135#[derive(Debug, Clone, PartialEq, Eq, Default)]
136pub struct NfNetlinkList<T>
137where
138    T: NfNetlinkDeserializable + NfNetlinkAttribute + Debug + Clone + Eq + Default,
139{
140    objs: Vec<T>,
141}
142
143impl<T> NfNetlinkList<T>
144where
145    T: NfNetlinkDeserializable + NfNetlinkAttribute + Clone + Eq + Default,
146{
147    pub fn add_value(&mut self, e: impl Into<T>) {
148        self.objs.push(e.into());
149    }
150
151    pub fn with_value(mut self, e: impl Into<T>) -> Self {
152        self.add_value(e);
153        self
154    }
155
156    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> {
157        self.objs.iter()
158    }
159
160    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> {
161        self.objs.iter_mut()
162    }
163}
164
165impl<T> NfNetlinkAttribute for NfNetlinkList<T>
166where
167    T: NfNetlinkDeserializable + NfNetlinkAttribute + Clone + Eq + Default,
168{
169    fn is_nested(&self) -> bool {
170        true
171    }
172
173    fn get_size(&self) -> usize {
174        // one nlattr LIST_ELEM per object
175        self.objs.iter().fold(0, |acc, item| {
176            acc + item.get_size() + pad_netlink_object::<nlattr>()
177        })
178    }
179
180    fn write_payload(&self, mut addr: &mut [u8]) {
181        for item in &self.objs {
182            write_attribute(NFTA_LIST_ELEM, item, addr);
183            let offset = pad_netlink_object::<nlattr>() + item.get_size();
184            addr = &mut addr[offset..];
185        }
186    }
187}
188
189impl<T> NfNetlinkDeserializable for NfNetlinkList<T>
190where
191    T: NfNetlinkDeserializable + NfNetlinkAttribute + Clone + Eq + Default,
192{
193    fn deserialize(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> {
194        let mut objs = Vec::new();
195
196        let mut pos = 0;
197        while buf.len() - pos > pad_netlink_object::<nlattr>() {
198            let nlattr = unsafe { *transmute::<*const u8, *const nlattr>(buf[pos..].as_ptr()) };
199            // ignore the byteorder and nested attributes
200            let nla_type = nlattr.nla_type & NLA_TYPE_MASK as u16;
201
202            if nla_type != NFTA_LIST_ELEM {
203                return Err(DecodeError::UnsupportedAttributeType(nla_type));
204            }
205
206            let (obj, remaining) = T::deserialize(
207                &buf[pos + pad_netlink_object::<nlattr>()..pos + nlattr.nla_len as usize],
208            )?;
209            if remaining.len() != 0 {
210                return Err(DecodeError::InvalidDataSize);
211            }
212            objs.push(obj);
213
214            pos += pad_netlink_object_with_variable_size(nlattr.nla_len as usize);
215        }
216
217        if pos != buf.len() {
218            Err(DecodeError::InvalidDataSize)
219        } else {
220            Ok((Self { objs }, &[]))
221        }
222    }
223}
224
225impl<O, T> From<Vec<O>> for NfNetlinkList<T>
226where
227    T: From<O>,
228    T: NfNetlinkDeserializable + NfNetlinkAttribute + Clone + Eq + Default,
229{
230    fn from(v: Vec<O>) -> Self {
231        NfNetlinkList {
232            objs: v.into_iter().map(T::from).collect(),
233        }
234    }
235}
236
237impl<T> NfNetlinkDeserializable for T
238where
239    T: NfNetlinkObject + AttributeDecoder + Default + Sized,
240{
241    fn deserialize(buf: &[u8]) -> Result<(T, &[u8]), DecodeError> {
242        let (mut obj, nfgenmsg, remaining_data) = parse_object::<T>(
243            buf,
244            <T as NfNetlinkObject>::MSG_TYPE_ADD,
245            <T as NfNetlinkObject>::MSG_TYPE_DEL,
246        )?;
247        obj.set_family(ProtocolFamily::try_from(nfgenmsg.nfgen_family as i32)?);
248
249        Ok((obj, remaining_data))
250    }
251}