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 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 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 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 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 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 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 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 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 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 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 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 pos = self.pos;
261        let mut r#type;
262        loop {
263            r#type = None;
264            if self.buf.len() == self.pos {
265                return None;
266            }
267            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
268                break;
269            };
270            r#type = Some(header.r#type);
271            let res = match header.r#type {
272                1u16 => Fou::Port({
273                    let res = parse_be_u16(next);
274                    let Some(val) = res else { break };
275                    val
276                }),
277                2u16 => Fou::Af({
278                    let res = parse_u8(next);
279                    let Some(val) = res else { break };
280                    val
281                }),
282                3u16 => Fou::Ipproto({
283                    let res = parse_u8(next);
284                    let Some(val) = res else { break };
285                    val
286                }),
287                4u16 => Fou::Type({
288                    let res = parse_u8(next);
289                    let Some(val) = res else { break };
290                    val
291                }),
292                5u16 => Fou::RemcsumNopartial(()),
293                6u16 => Fou::LocalV4({
294                    let res = parse_u32(next);
295                    let Some(val) = res else { break };
296                    val
297                }),
298                7u16 => Fou::LocalV6({
299                    let res = Some(next);
300                    let Some(val) = res else { break };
301                    val
302                }),
303                8u16 => Fou::PeerV4({
304                    let res = parse_u32(next);
305                    let Some(val) = res else { break };
306                    val
307                }),
308                9u16 => Fou::PeerV6({
309                    let res = Some(next);
310                    let Some(val) = res else { break };
311                    val
312                }),
313                10u16 => Fou::PeerPort({
314                    let res = parse_be_u16(next);
315                    let Some(val) = res else { break };
316                    val
317                }),
318                11u16 => Fou::Ifindex({
319                    let res = parse_i32(next);
320                    let Some(val) = res else { break };
321                    val
322                }),
323                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
324                n => continue,
325            };
326            return Some(Ok(res));
327        }
328        Some(Err(ErrorContext::new(
329            "Fou",
330            r#type.and_then(|t| Fou::attr_from_type(t)),
331            self.orig_loc,
332            self.buf.as_ptr().wrapping_add(pos) as usize,
333        )))
334    }
335}
336impl<'a> std::fmt::Debug for IterableFou<'_> {
337    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
338        let mut fmt = f.debug_struct("Fou");
339        for attr in self.clone() {
340            let attr = match attr {
341                Ok(a) => a,
342                Err(err) => {
343                    fmt.finish()?;
344                    f.write_str("Err(")?;
345                    err.fmt(f)?;
346                    return f.write_str(")");
347                }
348            };
349            match attr {
350                Fou::Port(val) => fmt.field("Port", &val),
351                Fou::Af(val) => fmt.field("Af", &val),
352                Fou::Ipproto(val) => fmt.field("Ipproto", &val),
353                Fou::Type(val) => fmt.field("Type", &val),
354                Fou::RemcsumNopartial(val) => fmt.field("RemcsumNopartial", &val),
355                Fou::LocalV4(val) => fmt.field("LocalV4", &val),
356                Fou::LocalV6(val) => fmt.field("LocalV6", &val),
357                Fou::PeerV4(val) => fmt.field("PeerV4", &val),
358                Fou::PeerV6(val) => fmt.field("PeerV6", &val),
359                Fou::PeerPort(val) => fmt.field("PeerPort", &val),
360                Fou::Ifindex(val) => fmt.field("Ifindex", &val),
361            };
362        }
363        fmt.finish()
364    }
365}
366impl IterableFou<'_> {
367    pub fn lookup_attr(
368        &self,
369        offset: usize,
370        missing_type: Option<u16>,
371    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
372        let mut stack = Vec::new();
373        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
374        if missing_type.is_some() && cur == offset {
375            stack.push(("Fou", offset));
376            return (stack, missing_type.and_then(|t| Fou::attr_from_type(t)));
377        }
378        if cur > offset || cur + self.buf.len() < offset {
379            return (stack, None);
380        }
381        let mut attrs = self.clone();
382        let mut last_off = cur + attrs.pos;
383        while let Some(attr) = attrs.next() {
384            let Ok(attr) = attr else { break };
385            match attr {
386                Fou::Port(val) => {
387                    if last_off == offset {
388                        stack.push(("Port", last_off));
389                        break;
390                    }
391                }
392                Fou::Af(val) => {
393                    if last_off == offset {
394                        stack.push(("Af", last_off));
395                        break;
396                    }
397                }
398                Fou::Ipproto(val) => {
399                    if last_off == offset {
400                        stack.push(("Ipproto", last_off));
401                        break;
402                    }
403                }
404                Fou::Type(val) => {
405                    if last_off == offset {
406                        stack.push(("Type", last_off));
407                        break;
408                    }
409                }
410                Fou::RemcsumNopartial(val) => {
411                    if last_off == offset {
412                        stack.push(("RemcsumNopartial", last_off));
413                        break;
414                    }
415                }
416                Fou::LocalV4(val) => {
417                    if last_off == offset {
418                        stack.push(("LocalV4", last_off));
419                        break;
420                    }
421                }
422                Fou::LocalV6(val) => {
423                    if last_off == offset {
424                        stack.push(("LocalV6", last_off));
425                        break;
426                    }
427                }
428                Fou::PeerV4(val) => {
429                    if last_off == offset {
430                        stack.push(("PeerV4", last_off));
431                        break;
432                    }
433                }
434                Fou::PeerV6(val) => {
435                    if last_off == offset {
436                        stack.push(("PeerV6", last_off));
437                        break;
438                    }
439                }
440                Fou::PeerPort(val) => {
441                    if last_off == offset {
442                        stack.push(("PeerPort", last_off));
443                        break;
444                    }
445                }
446                Fou::Ifindex(val) => {
447                    if last_off == offset {
448                        stack.push(("Ifindex", last_off));
449                        break;
450                    }
451                }
452                _ => {}
453            };
454            last_off = cur + attrs.pos;
455        }
456        if !stack.is_empty() {
457            stack.push(("Fou", cur));
458        }
459        (stack, None)
460    }
461}
462pub struct PushFou<Prev: Rec> {
463    pub(crate) prev: Option<Prev>,
464    pub(crate) header_offset: Option<usize>,
465}
466impl<Prev: Rec> Rec for PushFou<Prev> {
467    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
468        self.prev.as_mut().unwrap().as_rec_mut()
469    }
470    fn as_rec(&self) -> &Vec<u8> {
471        self.prev.as_ref().unwrap().as_rec()
472    }
473}
474impl<Prev: Rec> PushFou<Prev> {
475    pub fn new(prev: Prev) -> Self {
476        Self {
477            prev: Some(prev),
478            header_offset: None,
479        }
480    }
481    pub fn end_nested(mut self) -> Prev {
482        let mut prev = self.prev.take().unwrap();
483        if let Some(header_offset) = &self.header_offset {
484            finalize_nested_header(prev.as_rec_mut(), *header_offset);
485        }
486        prev
487    }
488    pub fn push_port(mut self, value: u16) -> Self {
489        push_header(self.as_rec_mut(), 1u16, 2 as u16);
490        self.as_rec_mut().extend(value.to_be_bytes());
491        self
492    }
493    pub fn push_af(mut self, value: u8) -> Self {
494        push_header(self.as_rec_mut(), 2u16, 1 as u16);
495        self.as_rec_mut().extend(value.to_ne_bytes());
496        self
497    }
498    pub fn push_ipproto(mut self, value: u8) -> Self {
499        push_header(self.as_rec_mut(), 3u16, 1 as u16);
500        self.as_rec_mut().extend(value.to_ne_bytes());
501        self
502    }
503    pub fn push_type(mut self, value: u8) -> Self {
504        push_header(self.as_rec_mut(), 4u16, 1 as u16);
505        self.as_rec_mut().extend(value.to_ne_bytes());
506        self
507    }
508    pub fn push_remcsum_nopartial(mut self, value: ()) -> Self {
509        push_header(self.as_rec_mut(), 5u16, 0 as u16);
510        self
511    }
512    pub fn push_local_v4(mut self, value: u32) -> Self {
513        push_header(self.as_rec_mut(), 6u16, 4 as u16);
514        self.as_rec_mut().extend(value.to_ne_bytes());
515        self
516    }
517    pub fn push_local_v6(mut self, value: &[u8]) -> Self {
518        push_header(self.as_rec_mut(), 7u16, value.len() as u16);
519        self.as_rec_mut().extend(value);
520        self
521    }
522    pub fn push_peer_v4(mut self, value: u32) -> Self {
523        push_header(self.as_rec_mut(), 8u16, 4 as u16);
524        self.as_rec_mut().extend(value.to_ne_bytes());
525        self
526    }
527    pub fn push_peer_v6(mut self, value: &[u8]) -> Self {
528        push_header(self.as_rec_mut(), 9u16, value.len() as u16);
529        self.as_rec_mut().extend(value);
530        self
531    }
532    pub fn push_peer_port(mut self, value: u16) -> Self {
533        push_header(self.as_rec_mut(), 10u16, 2 as u16);
534        self.as_rec_mut().extend(value.to_be_bytes());
535        self
536    }
537    pub fn push_ifindex(mut self, value: i32) -> Self {
538        push_header(self.as_rec_mut(), 11u16, 4 as u16);
539        self.as_rec_mut().extend(value.to_ne_bytes());
540        self
541    }
542}
543impl<Prev: Rec> Drop for PushFou<Prev> {
544    fn drop(&mut self) {
545        if let Some(prev) = &mut self.prev {
546            if let Some(header_offset) = &self.header_offset {
547                finalize_nested_header(prev.as_rec_mut(), *header_offset);
548            }
549        }
550    }
551}
552#[doc = "Add port\\.\nFlags: admin-perm\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"]
553#[derive(Debug)]
554pub struct OpAddDo<'r> {
555    request: Request<'r>,
556}
557impl<'r> OpAddDo<'r> {
558    pub fn new(mut request: Request<'r>) -> Self {
559        Self::write_header(request.buf_mut());
560        Self { request: request }
561    }
562    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
563        Self::write_header(buf);
564        PushFou::new(buf)
565    }
566    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
567        PushFou::new(self.request.buf_mut())
568    }
569    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
570        PushFou::new(self.request.buf)
571    }
572    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
573        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
574        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
575    }
576    fn write_header<Prev: Rec>(prev: &mut Prev) {
577        let mut header = BuiltinNfgenmsg::new();
578        header.cmd = 1u8;
579        header.version = 1u8;
580        prev.as_rec_mut().extend(header.as_slice());
581    }
582}
583impl NetlinkRequest for OpAddDo<'_> {
584    fn protocol(&self) -> Protocol {
585        Protocol::Generic("fou".as_bytes())
586    }
587    fn flags(&self) -> u16 {
588        self.request.flags
589    }
590    fn payload(&self) -> &[u8] {
591        self.request.buf()
592    }
593    type ReplyType<'buf> = IterableFou<'buf>;
594    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
595        Self::decode_request(buf)
596    }
597    fn lookup(
598        buf: &[u8],
599        offset: usize,
600        missing_type: Option<u16>,
601    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
602        Self::decode_request(buf).lookup_attr(offset, missing_type)
603    }
604}
605#[doc = "Delete port\\.\nFlags: admin-perm\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"]
606#[derive(Debug)]
607pub struct OpDelDo<'r> {
608    request: Request<'r>,
609}
610impl<'r> OpDelDo<'r> {
611    pub fn new(mut request: Request<'r>) -> Self {
612        Self::write_header(request.buf_mut());
613        Self { request: request }
614    }
615    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
616        Self::write_header(buf);
617        PushFou::new(buf)
618    }
619    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
620        PushFou::new(self.request.buf_mut())
621    }
622    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
623        PushFou::new(self.request.buf)
624    }
625    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
626        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
627        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
628    }
629    fn write_header<Prev: Rec>(prev: &mut Prev) {
630        let mut header = BuiltinNfgenmsg::new();
631        header.cmd = 2u8;
632        header.version = 1u8;
633        prev.as_rec_mut().extend(header.as_slice());
634    }
635}
636impl NetlinkRequest for OpDelDo<'_> {
637    fn protocol(&self) -> Protocol {
638        Protocol::Generic("fou".as_bytes())
639    }
640    fn flags(&self) -> u16 {
641        self.request.flags
642    }
643    fn payload(&self) -> &[u8] {
644        self.request.buf()
645    }
646    type ReplyType<'buf> = IterableFou<'buf>;
647    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
648        Self::decode_request(buf)
649    }
650    fn lookup(
651        buf: &[u8],
652        offset: usize,
653        missing_type: Option<u16>,
654    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
655        Self::decode_request(buf).lookup_attr(offset, missing_type)
656    }
657}
658#[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"]
659#[derive(Debug)]
660pub struct OpGetDump<'r> {
661    request: Request<'r>,
662}
663impl<'r> OpGetDump<'r> {
664    pub fn new(mut request: Request<'r>) -> Self {
665        Self::write_header(request.buf_mut());
666        Self {
667            request: request.set_dump(),
668        }
669    }
670    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
671        Self::write_header(buf);
672        PushFou::new(buf)
673    }
674    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
675        PushFou::new(self.request.buf_mut())
676    }
677    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
678        PushFou::new(self.request.buf)
679    }
680    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
681        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
682        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
683    }
684    fn write_header<Prev: Rec>(prev: &mut Prev) {
685        let mut header = BuiltinNfgenmsg::new();
686        header.cmd = 3u8;
687        header.version = 1u8;
688        prev.as_rec_mut().extend(header.as_slice());
689    }
690}
691impl NetlinkRequest for OpGetDump<'_> {
692    fn protocol(&self) -> Protocol {
693        Protocol::Generic("fou".as_bytes())
694    }
695    fn flags(&self) -> u16 {
696        self.request.flags
697    }
698    fn payload(&self) -> &[u8] {
699        self.request.buf()
700    }
701    type ReplyType<'buf> = IterableFou<'buf>;
702    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
703        Self::decode_request(buf)
704    }
705    fn lookup(
706        buf: &[u8],
707        offset: usize,
708        missing_type: Option<u16>,
709    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
710        Self::decode_request(buf).lookup_attr(offset, missing_type)
711    }
712}
713#[doc = "Get tunnel info\\.\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"]
714#[derive(Debug)]
715pub struct OpGetDo<'r> {
716    request: Request<'r>,
717}
718impl<'r> OpGetDo<'r> {
719    pub fn new(mut request: Request<'r>) -> Self {
720        Self::write_header(request.buf_mut());
721        Self { request: request }
722    }
723    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushFou<&'buf mut Vec<u8>> {
724        Self::write_header(buf);
725        PushFou::new(buf)
726    }
727    pub fn encode(&mut self) -> PushFou<&mut Vec<u8>> {
728        PushFou::new(self.request.buf_mut())
729    }
730    pub fn into_encoder(self) -> PushFou<RequestBuf<'r>> {
731        PushFou::new(self.request.buf)
732    }
733    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableFou<'a> {
734        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
735        IterableFou::with_loc(attrs, buf.as_ptr() as usize)
736    }
737    fn write_header<Prev: Rec>(prev: &mut Prev) {
738        let mut header = BuiltinNfgenmsg::new();
739        header.cmd = 3u8;
740        header.version = 1u8;
741        prev.as_rec_mut().extend(header.as_slice());
742    }
743}
744impl NetlinkRequest for OpGetDo<'_> {
745    fn protocol(&self) -> Protocol {
746        Protocol::Generic("fou".as_bytes())
747    }
748    fn flags(&self) -> u16 {
749        self.request.flags
750    }
751    fn payload(&self) -> &[u8] {
752        self.request.buf()
753    }
754    type ReplyType<'buf> = IterableFou<'buf>;
755    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
756        Self::decode_request(buf)
757    }
758    fn lookup(
759        buf: &[u8],
760        offset: usize,
761        missing_type: Option<u16>,
762    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
763        Self::decode_request(buf).lookup_attr(offset, missing_type)
764    }
765}
766use crate::traits::LookupFn;
767use crate::utils::RequestBuf;
768#[derive(Debug)]
769pub struct Request<'buf> {
770    buf: RequestBuf<'buf>,
771    flags: u16,
772    writeback: Option<&'buf mut Option<RequestInfo>>,
773}
774#[allow(unused)]
775#[derive(Debug, Clone)]
776pub struct RequestInfo {
777    protocol: Protocol,
778    flags: u16,
779    name: &'static str,
780    lookup: LookupFn,
781}
782impl Request<'static> {
783    pub fn new() -> Self {
784        Self::new_from_buf(Vec::new())
785    }
786    pub fn new_from_buf(buf: Vec<u8>) -> Self {
787        Self {
788            flags: 0,
789            buf: RequestBuf::Own(buf),
790            writeback: None,
791        }
792    }
793    pub fn into_buf(self) -> Vec<u8> {
794        match self.buf {
795            RequestBuf::Own(buf) => buf,
796            _ => unreachable!(),
797        }
798    }
799}
800impl<'buf> Request<'buf> {
801    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
802        buf.clear();
803        Self::new_extend(buf)
804    }
805    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
806        Self {
807            flags: 0,
808            buf: RequestBuf::Ref(buf),
809            writeback: None,
810        }
811    }
812    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
813        let Some(writeback) = &mut self.writeback else {
814            return;
815        };
816        **writeback = Some(RequestInfo {
817            protocol,
818            flags: self.flags,
819            name,
820            lookup,
821        })
822    }
823    pub fn buf(&self) -> &Vec<u8> {
824        self.buf.buf()
825    }
826    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
827        self.buf.buf_mut()
828    }
829    #[doc = "Set `NLM_F_CREATE` flag"]
830    pub fn set_create(mut self) -> Self {
831        self.flags |= consts::NLM_F_CREATE as u16;
832        self
833    }
834    #[doc = "Set `NLM_F_EXCL` flag"]
835    pub fn set_excl(mut self) -> Self {
836        self.flags |= consts::NLM_F_EXCL as u16;
837        self
838    }
839    #[doc = "Set `NLM_F_REPLACE` flag"]
840    pub fn set_replace(mut self) -> Self {
841        self.flags |= consts::NLM_F_REPLACE as u16;
842        self
843    }
844    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
845    pub fn set_change(self) -> Self {
846        self.set_create().set_replace()
847    }
848    #[doc = "Set `NLM_F_APPEND` flag"]
849    pub fn set_append(mut self) -> Self {
850        self.flags |= consts::NLM_F_APPEND as u16;
851        self
852    }
853    #[doc = "Set `self.flags |= flags`"]
854    pub fn set_flags(mut self, flags: u16) -> Self {
855        self.flags |= flags;
856        self
857    }
858    #[doc = "Set `self.flags ^= self.flags & flags`"]
859    pub fn unset_flags(mut self, flags: u16) -> Self {
860        self.flags ^= self.flags & flags;
861        self
862    }
863    #[doc = "Set `NLM_F_DUMP` flag"]
864    fn set_dump(mut self) -> Self {
865        self.flags |= consts::NLM_F_DUMP as u16;
866        self
867    }
868    #[doc = "Add port\\.\nFlags: admin-perm\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"]
869    pub fn op_add_do(self) -> OpAddDo<'buf> {
870        let mut res = OpAddDo::new(self);
871        res.request
872            .do_writeback(res.protocol(), "op-add-do", OpAddDo::lookup);
873        res
874    }
875    #[doc = "Delete port\\.\nFlags: admin-perm\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"]
876    pub fn op_del_do(self) -> OpDelDo<'buf> {
877        let mut res = OpDelDo::new(self);
878        res.request
879            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
880        res
881    }
882    #[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"]
883    pub fn op_get_dump(self) -> OpGetDump<'buf> {
884        let mut res = OpGetDump::new(self);
885        res.request
886            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
887        res
888    }
889    #[doc = "Get tunnel info\\.\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"]
890    pub fn op_get_do(self) -> OpGetDo<'buf> {
891        let mut res = OpGetDo::new(self);
892        res.request
893            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
894        res
895    }
896}
897#[cfg(test)]
898mod generated_tests {
899    use super::*;
900    #[test]
901    fn tests() {
902        let _ = IterableFou::get_ifindex;
903        let _ = IterableFou::get_ipproto;
904        let _ = IterableFou::get_local_v4;
905        let _ = IterableFou::get_local_v6;
906        let _ = IterableFou::get_peer_port;
907        let _ = IterableFou::get_peer_v4;
908        let _ = IterableFou::get_peer_v6;
909        let _ = IterableFou::get_port;
910        let _ = IterableFou::get_remcsum_nopartial;
911        let _ = IterableFou::get_type;
912        let _ = PushFou::<&mut Vec<u8>>::push_af;
913        let _ = PushFou::<&mut Vec<u8>>::push_ifindex;
914        let _ = PushFou::<&mut Vec<u8>>::push_ipproto;
915        let _ = PushFou::<&mut Vec<u8>>::push_local_v4;
916        let _ = PushFou::<&mut Vec<u8>>::push_local_v6;
917        let _ = PushFou::<&mut Vec<u8>>::push_peer_port;
918        let _ = PushFou::<&mut Vec<u8>>::push_peer_v4;
919        let _ = PushFou::<&mut Vec<u8>>::push_peer_v6;
920        let _ = PushFou::<&mut Vec<u8>>::push_port;
921        let _ = PushFou::<&mut Vec<u8>>::push_remcsum_nopartial;
922        let _ = PushFou::<&mut Vec<u8>>::push_type;
923    }
924}