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}