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