Skip to main content

netlink_bindings/fou/
mod.rs

1#![doc = "Foo-over-UDP.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "fou";
17pub const PROTONAME_CSTR: &CStr = c"fou";
18#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
19#[derive(Debug, Clone, Copy)]
20pub enum EncapType {
21    Unspec = 0,
22    Direct = 1,
23    Gue = 2,
24}
25impl EncapType {
26    pub fn from_value(value: u64) -> Option<Self> {
27        Some(match value {
28            0 => Self::Unspec,
29            1 => Self::Direct,
30            2 => Self::Gue,
31            _ => return None,
32        })
33    }
34}
35#[derive(Clone)]
36pub enum Fou<'a> {
37    Port(u16),
38    Af(u8),
39    Ipproto(u8),
40    Type(u8),
41    RemcsumNopartial(()),
42    LocalV4(u32),
43    LocalV6(&'a [u8]),
44    PeerV4(u32),
45    PeerV6(&'a [u8]),
46    PeerPort(u16),
47    Ifindex(i32),
48}
49impl<'a> IterableFou<'a> {
50    pub fn get_port(&self) -> Result<u16, ErrorContext> {
51        let mut iter = self.clone();
52        iter.pos = 0;
53        for attr in iter {
54            if let Ok(Fou::Port(val)) = attr {
55                return Ok(val);
56            }
57        }
58        Err(ErrorContext::new_missing(
59            "Fou",
60            "Port",
61            self.orig_loc,
62            self.buf.as_ptr() as usize,
63        ))
64    }
65    pub fn get_af(&self) -> Result<u8, ErrorContext> {
66        let mut iter = self.clone();
67        iter.pos = 0;
68        for attr in iter {
69            if let Ok(Fou::Af(val)) = attr {
70                return Ok(val);
71            }
72        }
73        Err(ErrorContext::new_missing(
74            "Fou",
75            "Af",
76            self.orig_loc,
77            self.buf.as_ptr() as usize,
78        ))
79    }
80    pub fn get_ipproto(&self) -> Result<u8, ErrorContext> {
81        let mut iter = self.clone();
82        iter.pos = 0;
83        for attr in iter {
84            if let Ok(Fou::Ipproto(val)) = attr {
85                return Ok(val);
86            }
87        }
88        Err(ErrorContext::new_missing(
89            "Fou",
90            "Ipproto",
91            self.orig_loc,
92            self.buf.as_ptr() as usize,
93        ))
94    }
95    pub fn get_type(&self) -> Result<u8, ErrorContext> {
96        let mut iter = self.clone();
97        iter.pos = 0;
98        for attr in iter {
99            if let Ok(Fou::Type(val)) = attr {
100                return Ok(val);
101            }
102        }
103        Err(ErrorContext::new_missing(
104            "Fou",
105            "Type",
106            self.orig_loc,
107            self.buf.as_ptr() as usize,
108        ))
109    }
110    pub fn get_remcsum_nopartial(&self) -> Result<(), ErrorContext> {
111        let mut iter = self.clone();
112        iter.pos = 0;
113        for attr in iter {
114            if let Ok(Fou::RemcsumNopartial(val)) = attr {
115                return Ok(val);
116            }
117        }
118        Err(ErrorContext::new_missing(
119            "Fou",
120            "RemcsumNopartial",
121            self.orig_loc,
122            self.buf.as_ptr() as usize,
123        ))
124    }
125    pub fn get_local_v4(&self) -> Result<u32, ErrorContext> {
126        let mut iter = self.clone();
127        iter.pos = 0;
128        for attr in iter {
129            if let Ok(Fou::LocalV4(val)) = attr {
130                return Ok(val);
131            }
132        }
133        Err(ErrorContext::new_missing(
134            "Fou",
135            "LocalV4",
136            self.orig_loc,
137            self.buf.as_ptr() as usize,
138        ))
139    }
140    pub fn get_local_v6(&self) -> Result<&'a [u8], ErrorContext> {
141        let mut iter = self.clone();
142        iter.pos = 0;
143        for attr in iter {
144            if let Ok(Fou::LocalV6(val)) = attr {
145                return Ok(val);
146            }
147        }
148        Err(ErrorContext::new_missing(
149            "Fou",
150            "LocalV6",
151            self.orig_loc,
152            self.buf.as_ptr() as usize,
153        ))
154    }
155    pub fn get_peer_v4(&self) -> Result<u32, ErrorContext> {
156        let mut iter = self.clone();
157        iter.pos = 0;
158        for attr in iter {
159            if let Ok(Fou::PeerV4(val)) = attr {
160                return Ok(val);
161            }
162        }
163        Err(ErrorContext::new_missing(
164            "Fou",
165            "PeerV4",
166            self.orig_loc,
167            self.buf.as_ptr() as usize,
168        ))
169    }
170    pub fn get_peer_v6(&self) -> Result<&'a [u8], ErrorContext> {
171        let mut iter = self.clone();
172        iter.pos = 0;
173        for attr in iter {
174            if let Ok(Fou::PeerV6(val)) = attr {
175                return Ok(val);
176            }
177        }
178        Err(ErrorContext::new_missing(
179            "Fou",
180            "PeerV6",
181            self.orig_loc,
182            self.buf.as_ptr() as usize,
183        ))
184    }
185    pub fn get_peer_port(&self) -> Result<u16, ErrorContext> {
186        let mut iter = self.clone();
187        iter.pos = 0;
188        for attr in iter {
189            if let Ok(Fou::PeerPort(val)) = attr {
190                return Ok(val);
191            }
192        }
193        Err(ErrorContext::new_missing(
194            "Fou",
195            "PeerPort",
196            self.orig_loc,
197            self.buf.as_ptr() as usize,
198        ))
199    }
200    pub fn get_ifindex(&self) -> Result<i32, ErrorContext> {
201        let mut iter = self.clone();
202        iter.pos = 0;
203        for attr in iter {
204            if let Ok(Fou::Ifindex(val)) = attr {
205                return Ok(val);
206            }
207        }
208        Err(ErrorContext::new_missing(
209            "Fou",
210            "Ifindex",
211            self.orig_loc,
212            self.buf.as_ptr() as usize,
213        ))
214    }
215}
216impl Fou<'_> {
217    pub fn new<'a>(buf: &'a [u8]) -> IterableFou<'a> {
218        IterableFou::with_loc(buf, buf.as_ptr() as usize)
219    }
220    fn attr_from_type(r#type: u16) -> Option<&'static str> {
221        let res = match r#type {
222            0u16 => "Unspec",
223            1u16 => "Port",
224            2u16 => "Af",
225            3u16 => "Ipproto",
226            4u16 => "Type",
227            5u16 => "RemcsumNopartial",
228            6u16 => "LocalV4",
229            7u16 => "LocalV6",
230            8u16 => "PeerV4",
231            9u16 => "PeerV6",
232            10u16 => "PeerPort",
233            11u16 => "Ifindex",
234            _ => return None,
235        };
236        Some(res)
237    }
238}
239#[derive(Clone, Copy, Default)]
240pub struct IterableFou<'a> {
241    buf: &'a [u8],
242    pos: usize,
243    orig_loc: usize,
244}
245impl<'a> IterableFou<'a> {
246    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
247        Self {
248            buf,
249            pos: 0,
250            orig_loc,
251        }
252    }
253    pub fn get_buf(&self) -> &'a [u8] {
254        self.buf
255    }
256}
257impl<'a> Iterator for IterableFou<'a> {
258    type Item = Result<Fou<'a>, ErrorContext>;
259    fn next(&mut self) -> Option<Self::Item> {
260        let mut pos;
261        let mut r#type;
262        loop {
263            pos = self.pos;
264            r#type = None;
265            if self.buf.len() == self.pos {
266                return None;
267            }
268            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
269                self.pos = self.buf.len();
270                break;
271            };
272            r#type = Some(header.r#type);
273            let res = match header.r#type {
274                1u16 => Fou::Port({
275                    let res = parse_be_u16(next);
276                    let Some(val) = res else { break };
277                    val
278                }),
279                2u16 => Fou::Af({
280                    let res = parse_u8(next);
281                    let Some(val) = res else { break };
282                    val
283                }),
284                3u16 => Fou::Ipproto({
285                    let res = parse_u8(next);
286                    let Some(val) = res else { break };
287                    val
288                }),
289                4u16 => Fou::Type({
290                    let res = parse_u8(next);
291                    let Some(val) = res else { break };
292                    val
293                }),
294                5u16 => Fou::RemcsumNopartial(()),
295                6u16 => Fou::LocalV4({
296                    let res = parse_u32(next);
297                    let Some(val) = res else { break };
298                    val
299                }),
300                7u16 => Fou::LocalV6({
301                    let res = Some(next);
302                    let Some(val) = res else { break };
303                    val
304                }),
305                8u16 => Fou::PeerV4({
306                    let res = parse_u32(next);
307                    let Some(val) = res else { break };
308                    val
309                }),
310                9u16 => Fou::PeerV6({
311                    let res = Some(next);
312                    let Some(val) = res else { break };
313                    val
314                }),
315                10u16 => Fou::PeerPort({
316                    let res = parse_be_u16(next);
317                    let Some(val) = res else { break };
318                    val
319                }),
320                11u16 => Fou::Ifindex({
321                    let res = parse_i32(next);
322                    let Some(val) = res else { break };
323                    val
324                }),
325                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
326                n => continue,
327            };
328            return Some(Ok(res));
329        }
330        Some(Err(ErrorContext::new(
331            "Fou",
332            r#type.and_then(|t| Fou::attr_from_type(t)),
333            self.orig_loc,
334            self.buf.as_ptr().wrapping_add(pos) as usize,
335        )))
336    }
337}
338impl<'a> std::fmt::Debug for IterableFou<'_> {
339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340        let mut fmt = f.debug_struct("Fou");
341        for attr in self.clone() {
342            let attr = match attr {
343                Ok(a) => a,
344                Err(err) => {
345                    fmt.finish()?;
346                    f.write_str("Err(")?;
347                    err.fmt(f)?;
348                    return f.write_str(")");
349                }
350            };
351            match attr {
352                Fou::Port(val) => fmt.field("Port", &val),
353                Fou::Af(val) => fmt.field("Af", &val),
354                Fou::Ipproto(val) => fmt.field("Ipproto", &val),
355                Fou::Type(val) => fmt.field("Type", &val),
356                Fou::RemcsumNopartial(val) => fmt.field("RemcsumNopartial", &val),
357                Fou::LocalV4(val) => fmt.field("LocalV4", &val),
358                Fou::LocalV6(val) => fmt.field("LocalV6", &val),
359                Fou::PeerV4(val) => fmt.field("PeerV4", &val),
360                Fou::PeerV6(val) => fmt.field("PeerV6", &val),
361                Fou::PeerPort(val) => fmt.field("PeerPort", &val),
362                Fou::Ifindex(val) => fmt.field("Ifindex", &val),
363            };
364        }
365        fmt.finish()
366    }
367}
368impl IterableFou<'_> {
369    pub fn lookup_attr(
370        &self,
371        offset: usize,
372        missing_type: Option<u16>,
373    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
374        let mut stack = Vec::new();
375        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
376        if missing_type.is_some() && cur == offset {
377            stack.push(("Fou", offset));
378            return (stack, missing_type.and_then(|t| Fou::attr_from_type(t)));
379        }
380        if cur > offset || cur + self.buf.len() < offset {
381            return (stack, None);
382        }
383        let mut attrs = self.clone();
384        let mut last_off = cur + attrs.pos;
385        while let Some(attr) = attrs.next() {
386            let Ok(attr) = attr else { break };
387            match attr {
388                Fou::Port(val) => {
389                    if last_off == offset {
390                        stack.push(("Port", last_off));
391                        break;
392                    }
393                }
394                Fou::Af(val) => {
395                    if last_off == offset {
396                        stack.push(("Af", last_off));
397                        break;
398                    }
399                }
400                Fou::Ipproto(val) => {
401                    if last_off == offset {
402                        stack.push(("Ipproto", last_off));
403                        break;
404                    }
405                }
406                Fou::Type(val) => {
407                    if last_off == offset {
408                        stack.push(("Type", last_off));
409                        break;
410                    }
411                }
412                Fou::RemcsumNopartial(val) => {
413                    if last_off == offset {
414                        stack.push(("RemcsumNopartial", last_off));
415                        break;
416                    }
417                }
418                Fou::LocalV4(val) => {
419                    if last_off == offset {
420                        stack.push(("LocalV4", last_off));
421                        break;
422                    }
423                }
424                Fou::LocalV6(val) => {
425                    if last_off == offset {
426                        stack.push(("LocalV6", last_off));
427                        break;
428                    }
429                }
430                Fou::PeerV4(val) => {
431                    if last_off == offset {
432                        stack.push(("PeerV4", last_off));
433                        break;
434                    }
435                }
436                Fou::PeerV6(val) => {
437                    if last_off == offset {
438                        stack.push(("PeerV6", last_off));
439                        break;
440                    }
441                }
442                Fou::PeerPort(val) => {
443                    if last_off == offset {
444                        stack.push(("PeerPort", last_off));
445                        break;
446                    }
447                }
448                Fou::Ifindex(val) => {
449                    if last_off == offset {
450                        stack.push(("Ifindex", last_off));
451                        break;
452                    }
453                }
454                _ => {}
455            };
456            last_off = cur + attrs.pos;
457        }
458        if !stack.is_empty() {
459            stack.push(("Fou", cur));
460        }
461        (stack, None)
462    }
463}
464pub struct PushFou<Prev: Pusher> {
465    pub(crate) prev: Option<Prev>,
466    pub(crate) header_offset: Option<usize>,
467}
468impl<Prev: Pusher> Pusher for PushFou<Prev> {
469    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
470        self.prev.as_mut().unwrap().as_vec_mut()
471    }
472    fn as_vec(&self) -> &Vec<u8> {
473        self.prev.as_ref().unwrap().as_vec()
474    }
475}
476impl<Prev: Pusher> PushFou<Prev> {
477    pub fn new(prev: Prev) -> Self {
478        Self {
479            prev: Some(prev),
480            header_offset: None,
481        }
482    }
483    pub fn end_nested(mut self) -> Prev {
484        let mut prev = self.prev.take().unwrap();
485        if let Some(header_offset) = &self.header_offset {
486            finalize_nested_header(prev.as_vec_mut(), *header_offset);
487        }
488        prev
489    }
490    pub fn push_port(mut self, value: u16) -> Self {
491        push_header(self.as_vec_mut(), 1u16, 2 as u16);
492        self.as_vec_mut().extend(value.to_be_bytes());
493        self
494    }
495    pub fn push_af(mut self, value: u8) -> Self {
496        push_header(self.as_vec_mut(), 2u16, 1 as u16);
497        self.as_vec_mut().extend(value.to_ne_bytes());
498        self
499    }
500    pub fn push_ipproto(mut self, value: u8) -> Self {
501        push_header(self.as_vec_mut(), 3u16, 1 as u16);
502        self.as_vec_mut().extend(value.to_ne_bytes());
503        self
504    }
505    pub fn push_type(mut self, value: u8) -> Self {
506        push_header(self.as_vec_mut(), 4u16, 1 as u16);
507        self.as_vec_mut().extend(value.to_ne_bytes());
508        self
509    }
510    pub fn push_remcsum_nopartial(mut self, value: ()) -> Self {
511        push_header(self.as_vec_mut(), 5u16, 0 as u16);
512        self
513    }
514    pub fn push_local_v4(mut self, value: u32) -> Self {
515        push_header(self.as_vec_mut(), 6u16, 4 as u16);
516        self.as_vec_mut().extend(value.to_ne_bytes());
517        self
518    }
519    pub fn push_local_v6(mut self, value: &[u8]) -> Self {
520        push_header(self.as_vec_mut(), 7u16, value.len() as u16);
521        self.as_vec_mut().extend(value);
522        self
523    }
524    pub fn push_peer_v4(mut self, value: u32) -> Self {
525        push_header(self.as_vec_mut(), 8u16, 4 as u16);
526        self.as_vec_mut().extend(value.to_ne_bytes());
527        self
528    }
529    pub fn push_peer_v6(mut self, value: &[u8]) -> Self {
530        push_header(self.as_vec_mut(), 9u16, value.len() as u16);
531        self.as_vec_mut().extend(value);
532        self
533    }
534    pub fn push_peer_port(mut self, value: u16) -> Self {
535        push_header(self.as_vec_mut(), 10u16, 2 as u16);
536        self.as_vec_mut().extend(value.to_be_bytes());
537        self
538    }
539    pub fn push_ifindex(mut self, value: i32) -> Self {
540        push_header(self.as_vec_mut(), 11u16, 4 as u16);
541        self.as_vec_mut().extend(value.to_ne_bytes());
542        self
543    }
544}
545impl<Prev: Pusher> Drop for PushFou<Prev> {
546    fn drop(&mut self) {
547        if let Some(prev) = &mut self.prev {
548            if let Some(header_offset) = &self.header_offset {
549                finalize_nested_header(prev.as_vec_mut(), *header_offset);
550            }
551        }
552    }
553}
554#[doc = "Add port.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_ipproto()](PushFou::push_ipproto)\n- [.push_type()](PushFou::push_type)\n- [.push_remcsum_nopartial()](PushFou::push_remcsum_nopartial)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\n"]
555#[derive(Debug)]
556pub struct OpAddDo<'r> {
557    request: Request<'r>,
558}
559impl<'r> OpAddDo<'r> {
560    pub fn new(mut request: Request<'r>) -> Self {
561        Self::write_header(request.buf_mut());
562        Self { request: request }
563    }
564    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
565        Self::write_header(buf);
566        PushFou::new(buf)
567    }
568    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
569        PushFou::new(self.request.buf_mut())
570    }
571    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
572        PushFou::new(self.request.buf)
573    }
574    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
575        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
576        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
577    }
578    fn write_header<Prev: Pusher>(prev: &mut Prev) {
579        let mut header = BuiltinNfgenmsg::new();
580        header.cmd = 1u8;
581        header.version = 1u8;
582        prev.as_vec_mut().extend(header.as_slice());
583    }
584}
585impl NetlinkRequest for OpAddDo<'_> {
586    fn protocol(&self) -> Protocol {
587        Protocol::Generic("fou".as_bytes())
588    }
589    fn flags(&self) -> u16 {
590        self.request.flags
591    }
592    fn payload(&self) -> &[u8] {
593        self.request.buf()
594    }
595    type ReplyType<'buf> = IterableFou<'buf>;
596    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
597        Self::decode_request(buf)
598    }
599    fn lookup(
600        buf: &[u8],
601        offset: usize,
602        missing_type: Option<u16>,
603    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
604        Self::decode_request(buf).lookup_attr(offset, missing_type)
605    }
606}
607#[doc = "Delete port.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_af()](PushFou::push_af)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\n"]
608#[derive(Debug)]
609pub struct OpDelDo<'r> {
610    request: Request<'r>,
611}
612impl<'r> OpDelDo<'r> {
613    pub fn new(mut request: Request<'r>) -> Self {
614        Self::write_header(request.buf_mut());
615        Self { request: request }
616    }
617    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
618        Self::write_header(buf);
619        PushFou::new(buf)
620    }
621    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
622        PushFou::new(self.request.buf_mut())
623    }
624    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
625        PushFou::new(self.request.buf)
626    }
627    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
628        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
629        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
630    }
631    fn write_header<Prev: Pusher>(prev: &mut Prev) {
632        let mut header = BuiltinNfgenmsg::new();
633        header.cmd = 2u8;
634        header.version = 1u8;
635        prev.as_vec_mut().extend(header.as_slice());
636    }
637}
638impl NetlinkRequest for OpDelDo<'_> {
639    fn protocol(&self) -> Protocol {
640        Protocol::Generic("fou".as_bytes())
641    }
642    fn flags(&self) -> u16 {
643        self.request.flags
644    }
645    fn payload(&self) -> &[u8] {
646        self.request.buf()
647    }
648    type ReplyType<'buf> = IterableFou<'buf>;
649    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
650        Self::decode_request(buf)
651    }
652    fn lookup(
653        buf: &[u8],
654        offset: usize,
655        missing_type: Option<u16>,
656    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
657        Self::decode_request(buf).lookup_attr(offset, missing_type)
658    }
659}
660#[doc = "Get tunnel info.\n\nReply attributes:\n- [.get_port()](IterableFou::get_port)\n- [.get_ipproto()](IterableFou::get_ipproto)\n- [.get_type()](IterableFou::get_type)\n- [.get_remcsum_nopartial()](IterableFou::get_remcsum_nopartial)\n- [.get_local_v4()](IterableFou::get_local_v4)\n- [.get_local_v6()](IterableFou::get_local_v6)\n- [.get_peer_v4()](IterableFou::get_peer_v4)\n- [.get_peer_v6()](IterableFou::get_peer_v6)\n- [.get_peer_port()](IterableFou::get_peer_port)\n- [.get_ifindex()](IterableFou::get_ifindex)\n\n"]
661#[derive(Debug)]
662pub struct OpGetDump<'r> {
663    request: Request<'r>,
664}
665impl<'r> OpGetDump<'r> {
666    pub fn new(mut request: Request<'r>) -> Self {
667        Self::write_header(request.buf_mut());
668        Self {
669            request: request.set_dump(),
670        }
671    }
672    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
673        Self::write_header(buf);
674        PushFou::new(buf)
675    }
676    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
677        PushFou::new(self.request.buf_mut())
678    }
679    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
680        PushFou::new(self.request.buf)
681    }
682    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
683        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
684        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
685    }
686    fn write_header<Prev: Pusher>(prev: &mut Prev) {
687        let mut header = BuiltinNfgenmsg::new();
688        header.cmd = 3u8;
689        header.version = 1u8;
690        prev.as_vec_mut().extend(header.as_slice());
691    }
692}
693impl NetlinkRequest for OpGetDump<'_> {
694    fn protocol(&self) -> Protocol {
695        Protocol::Generic("fou".as_bytes())
696    }
697    fn flags(&self) -> u16 {
698        self.request.flags
699    }
700    fn payload(&self) -> &[u8] {
701        self.request.buf()
702    }
703    type ReplyType<'buf> = IterableFou<'buf>;
704    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
705        Self::decode_request(buf)
706    }
707    fn lookup(
708        buf: &[u8],
709        offset: usize,
710        missing_type: Option<u16>,
711    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
712        Self::decode_request(buf).lookup_attr(offset, missing_type)
713    }
714}
715#[doc = "Get tunnel info.\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_af()](PushFou::push_af)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\nReply attributes:\n- [.get_port()](IterableFou::get_port)\n- [.get_ipproto()](IterableFou::get_ipproto)\n- [.get_type()](IterableFou::get_type)\n- [.get_remcsum_nopartial()](IterableFou::get_remcsum_nopartial)\n- [.get_local_v4()](IterableFou::get_local_v4)\n- [.get_local_v6()](IterableFou::get_local_v6)\n- [.get_peer_v4()](IterableFou::get_peer_v4)\n- [.get_peer_v6()](IterableFou::get_peer_v6)\n- [.get_peer_port()](IterableFou::get_peer_port)\n- [.get_ifindex()](IterableFou::get_ifindex)\n\n"]
716#[derive(Debug)]
717pub struct OpGetDo<'r> {
718    request: Request<'r>,
719}
720impl<'r> OpGetDo<'r> {
721    pub fn new(mut request: Request<'r>) -> Self {
722        Self::write_header(request.buf_mut());
723        Self { request: request }
724    }
725    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
726        Self::write_header(buf);
727        PushFou::new(buf)
728    }
729    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
730        PushFou::new(self.request.buf_mut())
731    }
732    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
733        PushFou::new(self.request.buf)
734    }
735    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
736        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
737        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
738    }
739    fn write_header<Prev: Pusher>(prev: &mut Prev) {
740        let mut header = BuiltinNfgenmsg::new();
741        header.cmd = 3u8;
742        header.version = 1u8;
743        prev.as_vec_mut().extend(header.as_slice());
744    }
745}
746impl NetlinkRequest for OpGetDo<'_> {
747    fn protocol(&self) -> Protocol {
748        Protocol::Generic("fou".as_bytes())
749    }
750    fn flags(&self) -> u16 {
751        self.request.flags
752    }
753    fn payload(&self) -> &[u8] {
754        self.request.buf()
755    }
756    type ReplyType<'buf> = IterableFou<'buf>;
757    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
758        Self::decode_request(buf)
759    }
760    fn lookup(
761        buf: &[u8],
762        offset: usize,
763        missing_type: Option<u16>,
764    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
765        Self::decode_request(buf).lookup_attr(offset, missing_type)
766    }
767}
768use crate::traits::LookupFn;
769use crate::utils::RequestBuf;
770#[derive(Debug)]
771pub struct Request<'buf> {
772    buf: RequestBuf<'buf>,
773    flags: u16,
774    writeback: Option<&'buf mut Option<RequestInfo>>,
775}
776#[allow(unused)]
777#[derive(Debug, Clone)]
778pub struct RequestInfo {
779    protocol: Protocol,
780    flags: u16,
781    name: &'static str,
782    lookup: LookupFn,
783}
784impl Request<'static> {
785    pub fn new() -> Self {
786        Self::new_from_buf(Vec::new())
787    }
788    pub fn new_from_buf(buf: Vec<u8>) -> Self {
789        Self {
790            flags: 0,
791            buf: RequestBuf::Own(buf),
792            writeback: None,
793        }
794    }
795    pub fn into_buf(self) -> Vec<u8> {
796        match self.buf {
797            RequestBuf::Own(buf) => buf,
798            _ => unreachable!(),
799        }
800    }
801}
802impl<'buf> Request<'buf> {
803    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
804        buf.clear();
805        Self::new_extend(buf)
806    }
807    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
808        Self {
809            flags: 0,
810            buf: RequestBuf::Ref(buf),
811            writeback: None,
812        }
813    }
814    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
815        let Some(writeback) = &mut self.writeback else {
816            return;
817        };
818        **writeback = Some(RequestInfo {
819            protocol,
820            flags: self.flags,
821            name,
822            lookup,
823        })
824    }
825    pub fn buf(&self) -> &Vec<u8> {
826        self.buf.buf()
827    }
828    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
829        self.buf.buf_mut()
830    }
831    #[doc = "Set `NLM_F_CREATE` flag"]
832    pub fn set_create(mut self) -> Self {
833        self.flags |= consts::NLM_F_CREATE as u16;
834        self
835    }
836    #[doc = "Set `NLM_F_EXCL` flag"]
837    pub fn set_excl(mut self) -> Self {
838        self.flags |= consts::NLM_F_EXCL as u16;
839        self
840    }
841    #[doc = "Set `NLM_F_REPLACE` flag"]
842    pub fn set_replace(mut self) -> Self {
843        self.flags |= consts::NLM_F_REPLACE as u16;
844        self
845    }
846    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
847    pub fn set_change(self) -> Self {
848        self.set_create().set_replace()
849    }
850    #[doc = "Set `NLM_F_APPEND` flag"]
851    pub fn set_append(mut self) -> Self {
852        self.flags |= consts::NLM_F_APPEND as u16;
853        self
854    }
855    #[doc = "Set `self.flags |= flags`"]
856    pub fn set_flags(mut self, flags: u16) -> Self {
857        self.flags |= flags;
858        self
859    }
860    #[doc = "Set `self.flags ^= self.flags & flags`"]
861    pub fn unset_flags(mut self, flags: u16) -> Self {
862        self.flags ^= self.flags & flags;
863        self
864    }
865    #[doc = "Set `NLM_F_DUMP` flag"]
866    fn set_dump(mut self) -> Self {
867        self.flags |= consts::NLM_F_DUMP as u16;
868        self
869    }
870    #[doc = "Add port.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_ipproto()](PushFou::push_ipproto)\n- [.push_type()](PushFou::push_type)\n- [.push_remcsum_nopartial()](PushFou::push_remcsum_nopartial)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\n"]
871    pub fn op_add_do(self) -> OpAddDo<'buf> {
872        let mut res = OpAddDo::new(self);
873        res.request
874            .do_writeback(res.protocol(), "op-add-do", OpAddDo::lookup);
875        res
876    }
877    #[doc = "Delete port.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_af()](PushFou::push_af)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\n"]
878    pub fn op_del_do(self) -> OpDelDo<'buf> {
879        let mut res = OpDelDo::new(self);
880        res.request
881            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
882        res
883    }
884    #[doc = "Get tunnel info.\n\nReply attributes:\n- [.get_port()](IterableFou::get_port)\n- [.get_ipproto()](IterableFou::get_ipproto)\n- [.get_type()](IterableFou::get_type)\n- [.get_remcsum_nopartial()](IterableFou::get_remcsum_nopartial)\n- [.get_local_v4()](IterableFou::get_local_v4)\n- [.get_local_v6()](IterableFou::get_local_v6)\n- [.get_peer_v4()](IterableFou::get_peer_v4)\n- [.get_peer_v6()](IterableFou::get_peer_v6)\n- [.get_peer_port()](IterableFou::get_peer_port)\n- [.get_ifindex()](IterableFou::get_ifindex)\n\n"]
885    pub fn op_get_dump(self) -> OpGetDump<'buf> {
886        let mut res = OpGetDump::new(self);
887        res.request
888            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
889        res
890    }
891    #[doc = "Get tunnel info.\n\nRequest attributes:\n- [.push_port()](PushFou::push_port)\n- [.push_af()](PushFou::push_af)\n- [.push_local_v4()](PushFou::push_local_v4)\n- [.push_local_v6()](PushFou::push_local_v6)\n- [.push_peer_v4()](PushFou::push_peer_v4)\n- [.push_peer_v6()](PushFou::push_peer_v6)\n- [.push_peer_port()](PushFou::push_peer_port)\n- [.push_ifindex()](PushFou::push_ifindex)\n\nReply attributes:\n- [.get_port()](IterableFou::get_port)\n- [.get_ipproto()](IterableFou::get_ipproto)\n- [.get_type()](IterableFou::get_type)\n- [.get_remcsum_nopartial()](IterableFou::get_remcsum_nopartial)\n- [.get_local_v4()](IterableFou::get_local_v4)\n- [.get_local_v6()](IterableFou::get_local_v6)\n- [.get_peer_v4()](IterableFou::get_peer_v4)\n- [.get_peer_v6()](IterableFou::get_peer_v6)\n- [.get_peer_port()](IterableFou::get_peer_port)\n- [.get_ifindex()](IterableFou::get_ifindex)\n\n"]
892    pub fn op_get_do(self) -> OpGetDo<'buf> {
893        let mut res = OpGetDo::new(self);
894        res.request
895            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
896        res
897    }
898}
899#[cfg(test)]
900mod generated_tests {
901    use super::*;
902    #[test]
903    fn tests() {
904        let _ = IterableFou::get_ifindex;
905        let _ = IterableFou::get_ipproto;
906        let _ = IterableFou::get_local_v4;
907        let _ = IterableFou::get_local_v6;
908        let _ = IterableFou::get_peer_port;
909        let _ = IterableFou::get_peer_v4;
910        let _ = IterableFou::get_peer_v6;
911        let _ = IterableFou::get_port;
912        let _ = IterableFou::get_remcsum_nopartial;
913        let _ = IterableFou::get_type;
914        let _ = PushFou::<&mut Vec<u8>>::push_af;
915        let _ = PushFou::<&mut Vec<u8>>::push_ifindex;
916        let _ = PushFou::<&mut Vec<u8>>::push_ipproto;
917        let _ = PushFou::<&mut Vec<u8>>::push_local_v4;
918        let _ = PushFou::<&mut Vec<u8>>::push_local_v6;
919        let _ = PushFou::<&mut Vec<u8>>::push_peer_port;
920        let _ = PushFou::<&mut Vec<u8>>::push_peer_v4;
921        let _ = PushFou::<&mut Vec<u8>>::push_peer_v6;
922        let _ = PushFou::<&mut Vec<u8>>::push_port;
923        let _ = PushFou::<&mut Vec<u8>>::push_remcsum_nopartial;
924        let _ = PushFou::<&mut Vec<u8>>::push_type;
925    }
926}