Skip to main content

netlink_bindings/unix-diag/
mod.rs

1#![doc = "UNIX socket diagnostics\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::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &CStr = c"unix-diag";
17pub const PROTONUM: u16 = 4u16;
18#[doc = "VFS inode info"]
19#[doc = "Receive queue length info"]
20#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
21#[derive(Debug, Clone, Copy)]
22pub enum ShowFlags {
23    #[doc = "show name (not path)"]
24    Name = 1 << 0,
25    #[doc = "show VFS inode info"]
26    Vfs = 1 << 1,
27    #[doc = "show peer socket info"]
28    Peer = 1 << 2,
29    #[doc = "show pending connections"]
30    Icons = 1 << 3,
31    #[doc = "show skb receive queue len"]
32    Rqlen = 1 << 4,
33    #[doc = "show memory info of a socket"]
34    Meminfo = 1 << 5,
35    #[doc = "show socket's UID"]
36    Uid = 1 << 6,
37}
38impl ShowFlags {
39    pub fn from_value(value: u64) -> Option<Self> {
40        Some(match value {
41            n if n == 1 << 0 => Self::Name,
42            n if n == 1 << 1 => Self::Vfs,
43            n if n == 1 << 2 => Self::Peer,
44            n if n == 1 << 3 => Self::Icons,
45            n if n == 1 << 4 => Self::Rqlen,
46            n if n == 1 << 5 => Self::Meminfo,
47            n if n == 1 << 6 => Self::Uid,
48            _ => return None,
49        })
50    }
51}
52#[derive(Clone)]
53pub enum UnixDiagAttrs<'a> {
54    #[doc = "Unix socket sun_path. May or may not contain '\\0'."]
55    Name(&'a [u8]),
56    Vfs(Vfs),
57    Peer(u32),
58    Icons(&'a [u8]),
59    Rqlen(Rqlen),
60    Meminfo(&'a [u8]),
61    Shutdown(u8),
62    Uid(u32),
63}
64impl<'a> IterableUnixDiagAttrs<'a> {
65    #[doc = "Unix socket sun_path. May or may not contain '\\0'."]
66    pub fn get_name(&self) -> Result<&'a [u8], ErrorContext> {
67        let mut iter = self.clone();
68        iter.pos = 0;
69        for attr in iter {
70            if let UnixDiagAttrs::Name(val) = attr? {
71                return Ok(val);
72            }
73        }
74        Err(ErrorContext::new_missing(
75            "UnixDiagAttrs",
76            "Name",
77            self.orig_loc,
78            self.buf.as_ptr() as usize,
79        ))
80    }
81    pub fn get_vfs(&self) -> Result<Vfs, ErrorContext> {
82        let mut iter = self.clone();
83        iter.pos = 0;
84        for attr in iter {
85            if let UnixDiagAttrs::Vfs(val) = attr? {
86                return Ok(val);
87            }
88        }
89        Err(ErrorContext::new_missing(
90            "UnixDiagAttrs",
91            "Vfs",
92            self.orig_loc,
93            self.buf.as_ptr() as usize,
94        ))
95    }
96    pub fn get_peer(&self) -> Result<u32, ErrorContext> {
97        let mut iter = self.clone();
98        iter.pos = 0;
99        for attr in iter {
100            if let UnixDiagAttrs::Peer(val) = attr? {
101                return Ok(val);
102            }
103        }
104        Err(ErrorContext::new_missing(
105            "UnixDiagAttrs",
106            "Peer",
107            self.orig_loc,
108            self.buf.as_ptr() as usize,
109        ))
110    }
111    pub fn get_icons(&self) -> Result<&'a [u8], ErrorContext> {
112        let mut iter = self.clone();
113        iter.pos = 0;
114        for attr in iter {
115            if let UnixDiagAttrs::Icons(val) = attr? {
116                return Ok(val);
117            }
118        }
119        Err(ErrorContext::new_missing(
120            "UnixDiagAttrs",
121            "Icons",
122            self.orig_loc,
123            self.buf.as_ptr() as usize,
124        ))
125    }
126    pub fn get_rqlen(&self) -> Result<Rqlen, ErrorContext> {
127        let mut iter = self.clone();
128        iter.pos = 0;
129        for attr in iter {
130            if let UnixDiagAttrs::Rqlen(val) = attr? {
131                return Ok(val);
132            }
133        }
134        Err(ErrorContext::new_missing(
135            "UnixDiagAttrs",
136            "Rqlen",
137            self.orig_loc,
138            self.buf.as_ptr() as usize,
139        ))
140    }
141    pub fn get_meminfo(&self) -> Result<&'a [u8], ErrorContext> {
142        let mut iter = self.clone();
143        iter.pos = 0;
144        for attr in iter {
145            if let UnixDiagAttrs::Meminfo(val) = attr? {
146                return Ok(val);
147            }
148        }
149        Err(ErrorContext::new_missing(
150            "UnixDiagAttrs",
151            "Meminfo",
152            self.orig_loc,
153            self.buf.as_ptr() as usize,
154        ))
155    }
156    pub fn get_shutdown(&self) -> Result<u8, ErrorContext> {
157        let mut iter = self.clone();
158        iter.pos = 0;
159        for attr in iter {
160            if let UnixDiagAttrs::Shutdown(val) = attr? {
161                return Ok(val);
162            }
163        }
164        Err(ErrorContext::new_missing(
165            "UnixDiagAttrs",
166            "Shutdown",
167            self.orig_loc,
168            self.buf.as_ptr() as usize,
169        ))
170    }
171    pub fn get_uid(&self) -> Result<u32, ErrorContext> {
172        let mut iter = self.clone();
173        iter.pos = 0;
174        for attr in iter {
175            if let UnixDiagAttrs::Uid(val) = attr? {
176                return Ok(val);
177            }
178        }
179        Err(ErrorContext::new_missing(
180            "UnixDiagAttrs",
181            "Uid",
182            self.orig_loc,
183            self.buf.as_ptr() as usize,
184        ))
185    }
186}
187impl UnixDiagAttrs<'_> {
188    pub fn new<'a>(buf: &'a [u8]) -> IterableUnixDiagAttrs<'a> {
189        IterableUnixDiagAttrs::with_loc(buf, buf.as_ptr() as usize)
190    }
191    fn attr_from_type(r#type: u16) -> Option<&'static str> {
192        let res = match r#type {
193            0u16 => "Name",
194            1u16 => "Vfs",
195            2u16 => "Peer",
196            3u16 => "Icons",
197            4u16 => "Rqlen",
198            5u16 => "Meminfo",
199            6u16 => "Shutdown",
200            7u16 => "Uid",
201            _ => return None,
202        };
203        Some(res)
204    }
205}
206#[derive(Clone, Copy, Default)]
207pub struct IterableUnixDiagAttrs<'a> {
208    buf: &'a [u8],
209    pos: usize,
210    orig_loc: usize,
211}
212impl<'a> IterableUnixDiagAttrs<'a> {
213    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
214        Self {
215            buf,
216            pos: 0,
217            orig_loc,
218        }
219    }
220    pub fn get_buf(&self) -> &'a [u8] {
221        self.buf
222    }
223}
224impl<'a> Iterator for IterableUnixDiagAttrs<'a> {
225    type Item = Result<UnixDiagAttrs<'a>, ErrorContext>;
226    fn next(&mut self) -> Option<Self::Item> {
227        let pos = self.pos;
228        let mut r#type;
229        loop {
230            r#type = None;
231            if self.buf.len() == self.pos {
232                return None;
233            }
234            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
235                break;
236            };
237            r#type = Some(header.r#type);
238            let res = match header.r#type {
239                0u16 => UnixDiagAttrs::Name({
240                    let res = Some(next);
241                    let Some(val) = res else { break };
242                    val
243                }),
244                1u16 => UnixDiagAttrs::Vfs({
245                    let res = Vfs::new_from_slice(next);
246                    let Some(val) = res else { break };
247                    val
248                }),
249                2u16 => UnixDiagAttrs::Peer({
250                    let res = parse_u32(next);
251                    let Some(val) = res else { break };
252                    val
253                }),
254                3u16 => UnixDiagAttrs::Icons({
255                    let res = Some(next);
256                    let Some(val) = res else { break };
257                    val
258                }),
259                4u16 => UnixDiagAttrs::Rqlen({
260                    let res = Rqlen::new_from_slice(next);
261                    let Some(val) = res else { break };
262                    val
263                }),
264                5u16 => UnixDiagAttrs::Meminfo({
265                    let res = Some(next);
266                    let Some(val) = res else { break };
267                    val
268                }),
269                6u16 => UnixDiagAttrs::Shutdown({
270                    let res = parse_u8(next);
271                    let Some(val) = res else { break };
272                    val
273                }),
274                7u16 => UnixDiagAttrs::Uid({
275                    let res = parse_u32(next);
276                    let Some(val) = res else { break };
277                    val
278                }),
279                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
280                n => continue,
281            };
282            return Some(Ok(res));
283        }
284        Some(Err(ErrorContext::new(
285            "UnixDiagAttrs",
286            r#type.and_then(|t| UnixDiagAttrs::attr_from_type(t)),
287            self.orig_loc,
288            self.buf.as_ptr().wrapping_add(pos) as usize,
289        )))
290    }
291}
292impl<'a> std::fmt::Debug for IterableUnixDiagAttrs<'_> {
293    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294        let mut fmt = f.debug_struct("UnixDiagAttrs");
295        for attr in self.clone() {
296            let attr = match attr {
297                Ok(a) => a,
298                Err(err) => {
299                    fmt.finish()?;
300                    f.write_str("Err(")?;
301                    err.fmt(f)?;
302                    return f.write_str(")");
303                }
304            };
305            match attr {
306                UnixDiagAttrs::Name(val) => fmt.field("Name", &FormatBinStr(val)),
307                UnixDiagAttrs::Vfs(val) => fmt.field("Vfs", &val),
308                UnixDiagAttrs::Peer(val) => fmt.field("Peer", &val),
309                UnixDiagAttrs::Icons(val) => fmt.field("Icons", &val),
310                UnixDiagAttrs::Rqlen(val) => fmt.field("Rqlen", &val),
311                UnixDiagAttrs::Meminfo(val) => fmt.field("Meminfo", &val),
312                UnixDiagAttrs::Shutdown(val) => fmt.field("Shutdown", &val),
313                UnixDiagAttrs::Uid(val) => fmt.field("Uid", &val),
314            };
315        }
316        fmt.finish()
317    }
318}
319impl IterableUnixDiagAttrs<'_> {
320    pub fn lookup_attr(
321        &self,
322        offset: usize,
323        missing_type: Option<u16>,
324    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
325        let mut stack = Vec::new();
326        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
327        if cur == offset {
328            stack.push(("UnixDiagAttrs", offset));
329            return (
330                stack,
331                missing_type.and_then(|t| UnixDiagAttrs::attr_from_type(t)),
332            );
333        }
334        if cur > offset || cur + self.buf.len() < offset {
335            return (stack, None);
336        }
337        let mut attrs = self.clone();
338        let mut last_off = cur + attrs.pos;
339        while let Some(attr) = attrs.next() {
340            let Ok(attr) = attr else { break };
341            match attr {
342                UnixDiagAttrs::Name(val) => {
343                    if last_off == offset {
344                        stack.push(("Name", last_off));
345                        break;
346                    }
347                }
348                UnixDiagAttrs::Vfs(val) => {
349                    if last_off == offset {
350                        stack.push(("Vfs", last_off));
351                        break;
352                    }
353                }
354                UnixDiagAttrs::Peer(val) => {
355                    if last_off == offset {
356                        stack.push(("Peer", last_off));
357                        break;
358                    }
359                }
360                UnixDiagAttrs::Icons(val) => {
361                    if last_off == offset {
362                        stack.push(("Icons", last_off));
363                        break;
364                    }
365                }
366                UnixDiagAttrs::Rqlen(val) => {
367                    if last_off == offset {
368                        stack.push(("Rqlen", last_off));
369                        break;
370                    }
371                }
372                UnixDiagAttrs::Meminfo(val) => {
373                    if last_off == offset {
374                        stack.push(("Meminfo", last_off));
375                        break;
376                    }
377                }
378                UnixDiagAttrs::Shutdown(val) => {
379                    if last_off == offset {
380                        stack.push(("Shutdown", last_off));
381                        break;
382                    }
383                }
384                UnixDiagAttrs::Uid(val) => {
385                    if last_off == offset {
386                        stack.push(("Uid", last_off));
387                        break;
388                    }
389                }
390                _ => {}
391            };
392            last_off = cur + attrs.pos;
393        }
394        if !stack.is_empty() {
395            stack.push(("UnixDiagAttrs", cur));
396        }
397        (stack, None)
398    }
399}
400pub struct PushUnixDiagAttrs<Prev: Rec> {
401    pub(crate) prev: Option<Prev>,
402    pub(crate) header_offset: Option<usize>,
403}
404impl<Prev: Rec> Rec for PushUnixDiagAttrs<Prev> {
405    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
406        self.prev.as_mut().unwrap().as_rec_mut()
407    }
408    fn as_rec(&self) -> &Vec<u8> {
409        self.prev.as_ref().unwrap().as_rec()
410    }
411}
412impl<Prev: Rec> PushUnixDiagAttrs<Prev> {
413    pub fn new(prev: Prev) -> Self {
414        Self {
415            prev: Some(prev),
416            header_offset: None,
417        }
418    }
419    pub fn end_nested(mut self) -> Prev {
420        let mut prev = self.prev.take().unwrap();
421        if let Some(header_offset) = &self.header_offset {
422            finalize_nested_header(prev.as_rec_mut(), *header_offset);
423        }
424        prev
425    }
426    #[doc = "Unix socket sun_path. May or may not contain '\\0'."]
427    pub fn push_name(mut self, value: &[u8]) -> Self {
428        push_header(self.as_rec_mut(), 0u16, value.len() as u16);
429        self.as_rec_mut().extend(value);
430        self
431    }
432    pub fn push_vfs(mut self, value: Vfs) -> Self {
433        push_header(self.as_rec_mut(), 1u16, value.as_slice().len() as u16);
434        self.as_rec_mut().extend(value.as_slice());
435        self
436    }
437    pub fn push_peer(mut self, value: u32) -> Self {
438        push_header(self.as_rec_mut(), 2u16, 4 as u16);
439        self.as_rec_mut().extend(value.to_ne_bytes());
440        self
441    }
442    pub fn push_icons(mut self, value: &[u8]) -> Self {
443        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
444        self.as_rec_mut().extend(value);
445        self
446    }
447    pub fn push_rqlen(mut self, value: Rqlen) -> Self {
448        push_header(self.as_rec_mut(), 4u16, value.as_slice().len() as u16);
449        self.as_rec_mut().extend(value.as_slice());
450        self
451    }
452    pub fn push_meminfo(mut self, value: &[u8]) -> Self {
453        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
454        self.as_rec_mut().extend(value);
455        self
456    }
457    pub fn push_shutdown(mut self, value: u8) -> Self {
458        push_header(self.as_rec_mut(), 6u16, 1 as u16);
459        self.as_rec_mut().extend(value.to_ne_bytes());
460        self
461    }
462    pub fn push_uid(mut self, value: u32) -> Self {
463        push_header(self.as_rec_mut(), 7u16, 4 as u16);
464        self.as_rec_mut().extend(value.to_ne_bytes());
465        self
466    }
467}
468impl<Prev: Rec> Drop for PushUnixDiagAttrs<Prev> {
469    fn drop(&mut self) {
470        if let Some(prev) = &mut self.prev {
471            if let Some(header_offset) = &self.header_offset {
472                finalize_nested_header(prev.as_rec_mut(), *header_offset);
473            }
474        }
475    }
476}
477#[repr(C, packed(4))]
478pub struct Req {
479    pub sdiag_family: u8,
480    pub sdiag_protocol: u8,
481    pub pad: u16,
482    #[doc = "States to dump"]
483    pub udiag_states: u32,
484    pub udiag_ino: u32,
485    #[doc = "Show flags"]
486    pub udiag_show: u32,
487    pub udiag_cookie: [u8; 8usize],
488}
489impl Clone for Req {
490    fn clone(&self) -> Self {
491        Self::new_from_array(*self.as_array())
492    }
493}
494#[doc = "Create zero-initialized struct"]
495impl Default for Req {
496    fn default() -> Self {
497        Self::new()
498    }
499}
500impl Req {
501    #[doc = "Create zero-initialized struct"]
502    pub fn new() -> Self {
503        Self::new_from_array([0u8; Self::len()])
504    }
505    #[doc = "Copy from contents from slice"]
506    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
507        if other.len() != Self::len() {
508            return None;
509        }
510        let mut buf = [0u8; Self::len()];
511        buf.clone_from_slice(other);
512        Some(Self::new_from_array(buf))
513    }
514    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
515    pub fn new_from_zeroed(other: &[u8]) -> Self {
516        let mut buf = [0u8; Self::len()];
517        let len = buf.len().min(other.len());
518        buf[..len].clone_from_slice(&other[..len]);
519        Self::new_from_array(buf)
520    }
521    pub fn new_from_array(buf: [u8; 24usize]) -> Self {
522        unsafe { std::mem::transmute(buf) }
523    }
524    pub fn as_slice(&self) -> &[u8] {
525        unsafe {
526            let ptr: *const u8 = std::mem::transmute(self as *const Self);
527            std::slice::from_raw_parts(ptr, Self::len())
528        }
529    }
530    pub fn from_slice(buf: &[u8]) -> &Self {
531        assert!(buf.len() >= Self::len());
532        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
533        unsafe { std::mem::transmute(buf.as_ptr()) }
534    }
535    pub fn as_array(&self) -> &[u8; 24usize] {
536        unsafe { std::mem::transmute(self) }
537    }
538    pub fn from_array(buf: &[u8; 24usize]) -> &Self {
539        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
540        unsafe { std::mem::transmute(buf) }
541    }
542    pub fn into_array(self) -> [u8; 24usize] {
543        unsafe { std::mem::transmute(self) }
544    }
545    pub const fn len() -> usize {
546        const _: () = assert!(std::mem::size_of::<Req>() == 24usize);
547        24usize
548    }
549}
550impl std::fmt::Debug for Req {
551    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552        fmt.debug_struct("Req")
553            .field("sdiag_family", &self.sdiag_family)
554            .field("sdiag_protocol", &self.sdiag_protocol)
555            .field("pad", &self.pad)
556            .field("udiag_states", &self.udiag_states)
557            .field("udiag_ino", &self.udiag_ino)
558            .field("udiag_show", &self.udiag_show)
559            .field("udiag_cookie", &FormatHex(self.udiag_cookie))
560            .finish()
561    }
562}
563#[repr(C, packed(4))]
564pub struct Msg {
565    pub udiag_family: u8,
566    pub udiag_type: u8,
567    pub udiag_state: u8,
568    pub pad: u8,
569    pub udiag_ino: u32,
570    pub udiag_cookie: [u8; 8usize],
571}
572impl Clone for Msg {
573    fn clone(&self) -> Self {
574        Self::new_from_array(*self.as_array())
575    }
576}
577#[doc = "Create zero-initialized struct"]
578impl Default for Msg {
579    fn default() -> Self {
580        Self::new()
581    }
582}
583impl Msg {
584    #[doc = "Create zero-initialized struct"]
585    pub fn new() -> Self {
586        Self::new_from_array([0u8; Self::len()])
587    }
588    #[doc = "Copy from contents from slice"]
589    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
590        if other.len() != Self::len() {
591            return None;
592        }
593        let mut buf = [0u8; Self::len()];
594        buf.clone_from_slice(other);
595        Some(Self::new_from_array(buf))
596    }
597    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
598    pub fn new_from_zeroed(other: &[u8]) -> Self {
599        let mut buf = [0u8; Self::len()];
600        let len = buf.len().min(other.len());
601        buf[..len].clone_from_slice(&other[..len]);
602        Self::new_from_array(buf)
603    }
604    pub fn new_from_array(buf: [u8; 16usize]) -> Self {
605        unsafe { std::mem::transmute(buf) }
606    }
607    pub fn as_slice(&self) -> &[u8] {
608        unsafe {
609            let ptr: *const u8 = std::mem::transmute(self as *const Self);
610            std::slice::from_raw_parts(ptr, Self::len())
611        }
612    }
613    pub fn from_slice(buf: &[u8]) -> &Self {
614        assert!(buf.len() >= Self::len());
615        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
616        unsafe { std::mem::transmute(buf.as_ptr()) }
617    }
618    pub fn as_array(&self) -> &[u8; 16usize] {
619        unsafe { std::mem::transmute(self) }
620    }
621    pub fn from_array(buf: &[u8; 16usize]) -> &Self {
622        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
623        unsafe { std::mem::transmute(buf) }
624    }
625    pub fn into_array(self) -> [u8; 16usize] {
626        unsafe { std::mem::transmute(self) }
627    }
628    pub const fn len() -> usize {
629        const _: () = assert!(std::mem::size_of::<Msg>() == 16usize);
630        16usize
631    }
632}
633impl std::fmt::Debug for Msg {
634    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
635        fmt.debug_struct("Msg")
636            .field("udiag_family", &self.udiag_family)
637            .field("udiag_type", &self.udiag_type)
638            .field("udiag_state", &self.udiag_state)
639            .field("pad", &self.pad)
640            .field("udiag_ino", &self.udiag_ino)
641            .field("udiag_cookie", &FormatHex(self.udiag_cookie))
642            .finish()
643    }
644}
645#[derive(Debug)]
646#[repr(C, packed(4))]
647pub struct Vfs {
648    pub udiag_vfs_ino: u32,
649    pub udiag_vfs_dev: u32,
650}
651impl Clone for Vfs {
652    fn clone(&self) -> Self {
653        Self::new_from_array(*self.as_array())
654    }
655}
656#[doc = "Create zero-initialized struct"]
657impl Default for Vfs {
658    fn default() -> Self {
659        Self::new()
660    }
661}
662impl Vfs {
663    #[doc = "Create zero-initialized struct"]
664    pub fn new() -> Self {
665        Self::new_from_array([0u8; Self::len()])
666    }
667    #[doc = "Copy from contents from slice"]
668    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
669        if other.len() != Self::len() {
670            return None;
671        }
672        let mut buf = [0u8; Self::len()];
673        buf.clone_from_slice(other);
674        Some(Self::new_from_array(buf))
675    }
676    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
677    pub fn new_from_zeroed(other: &[u8]) -> Self {
678        let mut buf = [0u8; Self::len()];
679        let len = buf.len().min(other.len());
680        buf[..len].clone_from_slice(&other[..len]);
681        Self::new_from_array(buf)
682    }
683    pub fn new_from_array(buf: [u8; 8usize]) -> Self {
684        unsafe { std::mem::transmute(buf) }
685    }
686    pub fn as_slice(&self) -> &[u8] {
687        unsafe {
688            let ptr: *const u8 = std::mem::transmute(self as *const Self);
689            std::slice::from_raw_parts(ptr, Self::len())
690        }
691    }
692    pub fn from_slice(buf: &[u8]) -> &Self {
693        assert!(buf.len() >= Self::len());
694        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
695        unsafe { std::mem::transmute(buf.as_ptr()) }
696    }
697    pub fn as_array(&self) -> &[u8; 8usize] {
698        unsafe { std::mem::transmute(self) }
699    }
700    pub fn from_array(buf: &[u8; 8usize]) -> &Self {
701        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
702        unsafe { std::mem::transmute(buf) }
703    }
704    pub fn into_array(self) -> [u8; 8usize] {
705        unsafe { std::mem::transmute(self) }
706    }
707    pub const fn len() -> usize {
708        const _: () = assert!(std::mem::size_of::<Vfs>() == 8usize);
709        8usize
710    }
711}
712#[derive(Debug)]
713#[repr(C, packed(4))]
714pub struct Rqlen {
715    pub udiag_rqueue: u32,
716    pub udiag_wqueue: u32,
717}
718impl Clone for Rqlen {
719    fn clone(&self) -> Self {
720        Self::new_from_array(*self.as_array())
721    }
722}
723#[doc = "Create zero-initialized struct"]
724impl Default for Rqlen {
725    fn default() -> Self {
726        Self::new()
727    }
728}
729impl Rqlen {
730    #[doc = "Create zero-initialized struct"]
731    pub fn new() -> Self {
732        Self::new_from_array([0u8; Self::len()])
733    }
734    #[doc = "Copy from contents from slice"]
735    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
736        if other.len() != Self::len() {
737            return None;
738        }
739        let mut buf = [0u8; Self::len()];
740        buf.clone_from_slice(other);
741        Some(Self::new_from_array(buf))
742    }
743    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
744    pub fn new_from_zeroed(other: &[u8]) -> Self {
745        let mut buf = [0u8; Self::len()];
746        let len = buf.len().min(other.len());
747        buf[..len].clone_from_slice(&other[..len]);
748        Self::new_from_array(buf)
749    }
750    pub fn new_from_array(buf: [u8; 8usize]) -> Self {
751        unsafe { std::mem::transmute(buf) }
752    }
753    pub fn as_slice(&self) -> &[u8] {
754        unsafe {
755            let ptr: *const u8 = std::mem::transmute(self as *const Self);
756            std::slice::from_raw_parts(ptr, Self::len())
757        }
758    }
759    pub fn from_slice(buf: &[u8]) -> &Self {
760        assert!(buf.len() >= Self::len());
761        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
762        unsafe { std::mem::transmute(buf.as_ptr()) }
763    }
764    pub fn as_array(&self) -> &[u8; 8usize] {
765        unsafe { std::mem::transmute(self) }
766    }
767    pub fn from_array(buf: &[u8; 8usize]) -> &Self {
768        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
769        unsafe { std::mem::transmute(buf) }
770    }
771    pub fn into_array(self) -> [u8; 8usize] {
772        unsafe { std::mem::transmute(self) }
773    }
774    pub const fn len() -> usize {
775        const _: () = assert!(std::mem::size_of::<Rqlen>() == 8usize);
776        8usize
777    }
778}
779#[derive(Debug)]
780pub struct RequestOpUnixDiagDumpRequest<'r> {
781    request: Request<'r>,
782}
783impl<'r> RequestOpUnixDiagDumpRequest<'r> {
784    pub fn new(mut request: Request<'r>, header: &Req) -> Self {
785        Self::write_header(&mut request.buf_mut(), header);
786        Self {
787            request: request.set_dump(),
788        }
789    }
790    pub fn encode(&mut self) -> PushUnixDiagAttrs<&mut Vec<u8>> {
791        PushUnixDiagAttrs::new(self.request.buf_mut())
792    }
793    pub fn into_encoder(self) -> PushUnixDiagAttrs<RequestBuf<'r>> {
794        PushUnixDiagAttrs::new(self.request.buf)
795    }
796    fn write_header<Prev: Rec>(prev: &mut Prev, header: &Req) {
797        prev.as_rec_mut().extend(header.as_slice());
798    }
799    pub fn decode_request<'a>(buf: &'a [u8]) -> (Req, IterableUnixDiagAttrs<'a>) {
800        let (header, attrs) = buf.split_at(buf.len().min(Req::len()));
801        (
802            Req::new_from_slice(header).unwrap_or_default(),
803            IterableUnixDiagAttrs::with_loc(attrs, buf.as_ptr() as usize),
804        )
805    }
806    fn decode_reply<'a>(buf: &'a [u8]) -> (Msg, IterableUnixDiagAttrs<'a>) {
807        let (header, attrs) = buf.split_at(buf.len().min(Msg::len()));
808        (
809            Msg::new_from_slice(header).unwrap_or_default(),
810            IterableUnixDiagAttrs::with_loc(attrs, buf.as_ptr() as usize),
811        )
812    }
813}
814impl NetlinkRequest for RequestOpUnixDiagDumpRequest<'_> {
815    fn protocol(&self) -> Protocol {
816        Protocol::Raw {
817            protonum: 4u16,
818            request_type: 20u16,
819        }
820    }
821    fn flags(&self) -> u16 {
822        self.request.flags
823    }
824    fn payload(&self) -> &[u8] {
825        self.request.buf()
826    }
827    type ReplyType<'buf> = (Msg, IterableUnixDiagAttrs<'buf>);
828    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
829        Self::decode_reply(buf)
830    }
831    fn lookup(
832        buf: &[u8],
833        offset: usize,
834        missing_type: Option<u16>,
835    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
836        Self::decode_request(buf)
837            .1
838            .lookup_attr(offset, missing_type)
839    }
840}
841#[derive(Debug)]
842pub struct ChainedFinal<'a> {
843    inner: Chained<'a>,
844}
845#[derive(Debug)]
846pub struct Chained<'a> {
847    buf: RequestBuf<'a>,
848    first_seq: u32,
849    lookups: Vec<(&'static str, LookupFn)>,
850    last_header_offset: usize,
851    last_kind: Option<RequestInfo>,
852}
853impl<'a> ChainedFinal<'a> {
854    pub fn into_chained(self) -> Chained<'a> {
855        self.inner
856    }
857    pub fn buf(&self) -> &Vec<u8> {
858        self.inner.buf()
859    }
860    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
861        self.inner.buf_mut()
862    }
863    fn get_index(&self, seq: u32) -> Option<u32> {
864        let min = self.inner.first_seq;
865        let max = min.wrapping_add(self.inner.lookups.len() as u32);
866        return if min <= max {
867            (min..max).contains(&seq).then(|| seq - min)
868        } else if min <= seq {
869            Some(seq - min)
870        } else if seq < max {
871            Some(u32::MAX - min + seq)
872        } else {
873            None
874        };
875    }
876}
877impl crate::traits::NetlinkChained for ChainedFinal<'_> {
878    fn protonum(&self) -> u16 {
879        PROTONUM
880    }
881    fn payload(&self) -> &[u8] {
882        self.buf()
883    }
884    fn chain_len(&self) -> usize {
885        self.inner.lookups.len()
886    }
887    fn get_index(&self, seq: u32) -> Option<usize> {
888        self.get_index(seq).map(|n| n as usize)
889    }
890    fn name(&self, index: usize) -> &'static str {
891        self.inner.lookups[index].0
892    }
893    fn lookup(&self, index: usize) -> LookupFn {
894        self.inner.lookups[index].1
895    }
896}
897impl Chained<'static> {
898    pub fn new(first_seq: u32) -> Self {
899        Self::new_from_buf(Vec::new(), first_seq)
900    }
901    pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
902        Self {
903            buf: RequestBuf::Own(buf),
904            first_seq,
905            lookups: Vec::new(),
906            last_header_offset: 0,
907            last_kind: None,
908        }
909    }
910    pub fn into_buf(self) -> Vec<u8> {
911        match self.buf {
912            RequestBuf::Own(buf) => buf,
913            _ => unreachable!(),
914        }
915    }
916}
917impl<'a> Chained<'a> {
918    pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
919        Self {
920            buf: RequestBuf::Ref(buf),
921            first_seq,
922            lookups: Vec::new(),
923            last_header_offset: 0,
924            last_kind: None,
925        }
926    }
927    pub fn finalize(mut self) -> ChainedFinal<'a> {
928        self.update_header();
929        ChainedFinal { inner: self }
930    }
931    pub fn request(&mut self) -> Request<'_> {
932        self.update_header();
933        self.last_header_offset = self.buf().len();
934        self.buf_mut()
935            .extend_from_slice(PushNlmsghdr::new().as_slice());
936        let mut request = Request::new_extend(self.buf.buf_mut());
937        self.last_kind = None;
938        request.writeback = Some(&mut self.last_kind);
939        request
940    }
941    pub fn buf(&self) -> &Vec<u8> {
942        self.buf.buf()
943    }
944    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
945        self.buf.buf_mut()
946    }
947    fn update_header(&mut self) {
948        let Some(RequestInfo {
949            protocol,
950            flags,
951            name,
952            lookup,
953        }) = self.last_kind
954        else {
955            if !self.buf().is_empty() {
956                assert_eq!(
957                    self.last_header_offset + PushNlmsghdr::len(),
958                    self.buf().len()
959                );
960                self.buf.buf_mut().truncate(self.last_header_offset);
961            }
962            return;
963        };
964        let header_offset = self.last_header_offset;
965        let request_type = match protocol {
966            Protocol::Raw { request_type, .. } => request_type,
967            Protocol::Generic(_) => unreachable!(),
968        };
969        let index = self.lookups.len();
970        let seq = self.first_seq.wrapping_add(index as u32);
971        self.lookups.push((name, lookup));
972        let buf = self.buf_mut();
973        align(buf);
974        let mut header = PushNlmsghdr::new();
975        header.set_len((buf.len() - header_offset) as u32);
976        header.set_type(request_type);
977        header.set_flags(flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16);
978        header.set_seq(seq);
979        buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
980    }
981}
982use crate::traits::LookupFn;
983use crate::utils::RequestBuf;
984#[derive(Debug)]
985pub struct Request<'buf> {
986    buf: RequestBuf<'buf>,
987    flags: u16,
988    writeback: Option<&'buf mut Option<RequestInfo>>,
989}
990#[allow(unused)]
991#[derive(Debug, Clone)]
992pub struct RequestInfo {
993    protocol: Protocol,
994    flags: u16,
995    name: &'static str,
996    lookup: LookupFn,
997}
998impl Request<'static> {
999    pub fn new() -> Self {
1000        Self::new_from_buf(Vec::new())
1001    }
1002    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1003        Self {
1004            flags: 0,
1005            buf: RequestBuf::Own(buf),
1006            writeback: None,
1007        }
1008    }
1009    pub fn into_buf(self) -> Vec<u8> {
1010        match self.buf {
1011            RequestBuf::Own(buf) => buf,
1012            _ => unreachable!(),
1013        }
1014    }
1015}
1016impl<'buf> Request<'buf> {
1017    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1018        buf.clear();
1019        Self::new_extend(buf)
1020    }
1021    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1022        Self {
1023            flags: 0,
1024            buf: RequestBuf::Ref(buf),
1025            writeback: None,
1026        }
1027    }
1028    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1029        let Some(writeback) = &mut self.writeback else {
1030            return;
1031        };
1032        **writeback = Some(RequestInfo {
1033            protocol,
1034            flags: self.flags,
1035            name,
1036            lookup,
1037        })
1038    }
1039    pub fn buf(&self) -> &Vec<u8> {
1040        self.buf.buf()
1041    }
1042    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1043        self.buf.buf_mut()
1044    }
1045    #[doc = "Set `NLM_F_CREATE` flag"]
1046    pub fn set_create(mut self) -> Self {
1047        self.flags |= consts::NLM_F_CREATE as u16;
1048        self
1049    }
1050    #[doc = "Set `NLM_F_EXCL` flag"]
1051    pub fn set_excl(mut self) -> Self {
1052        self.flags |= consts::NLM_F_EXCL as u16;
1053        self
1054    }
1055    #[doc = "Set `NLM_F_REPLACE` flag"]
1056    pub fn set_replace(mut self) -> Self {
1057        self.flags |= consts::NLM_F_REPLACE as u16;
1058        self
1059    }
1060    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1061    pub fn set_change(self) -> Self {
1062        self.set_create().set_replace()
1063    }
1064    #[doc = "Set `NLM_F_APPEND` flag"]
1065    pub fn set_append(mut self) -> Self {
1066        self.flags |= consts::NLM_F_APPEND as u16;
1067        self
1068    }
1069    #[doc = "Set `NLM_F_DUMP` flag"]
1070    fn set_dump(mut self) -> Self {
1071        self.flags |= consts::NLM_F_DUMP as u16;
1072        self
1073    }
1074    pub fn op_unix_diag_dump_request(self, header: &Req) -> RequestOpUnixDiagDumpRequest<'buf> {
1075        let mut res = RequestOpUnixDiagDumpRequest::new(self, header);
1076        res.request.do_writeback(
1077            res.protocol(),
1078            "op-unix-diag-dump-request",
1079            RequestOpUnixDiagDumpRequest::lookup,
1080        );
1081        res
1082    }
1083}