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 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 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 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}