1#![doc = "Internet 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"inet-diag";
17pub const PROTONUM: u16 = 4u16;
18pub const TCPDIAG_GETSOCK_CONST: u64 = 18u64;
19pub const DCCPDIAG_GETSOCK_CONST: u64 = 19u64;
20pub const GETSOCK_MAX_CONST: u64 = 24u64;
21pub const NOCOOKIE_CONST: u64 = 4294967295u64;
22#[doc = "Socket identity"]
23#[doc = "SOCK_RAW sockets require the underlied protocol to be additionally\nspecified so we can use @pad member for this, but we can't rename it\nbecause userspace programs still may depend on this name. Instead lets\nuse another structure definition as an alias for struct\n@inet_diag_req_v2.\n"]
24#[doc = "Base info structure. It contains socket identity (addrs/ports/cookie)\nand, alas, the information shown by netstat.\n"]
25#[doc = "Bytecode is sequence of 4 byte commands followed by variable arguments.\nAll the commands identified by \"code\" are conditional jumps forward: to\noffset cc+\"yes\" (bytes) or to offset cc+\"no\" (bytes). \"yes\" is supposed\nto be length of the command and its arguments (in bytes).\n\nTermination condition is to land excactly on a len'th instruction (on\naddress of one after the last one), overshooting means an unsucessfull\ntermination.\n\nIf you reading this, for your own sanity, I advice you to first try\nreverse-lookup on the `ss` command with filters you need, and copy\nbytecode from there.\n"]
26#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
27#[derive(Debug, Clone, Copy)]
28pub enum BytecodeOpCode {
29 Nop = 0,
30 #[doc = "unconditional jump. \"no\" value is ignored."]
31 Jmp = 1,
32 #[doc = "sock.sport >= next_instruction.no (big endian)"]
33 SportGe = 2,
34 #[doc = "sock.sport <= next_instruction.no (big endian)"]
35 SportLe = 3,
36 #[doc = "sock.dport >= next_instruction.no (big endian)"]
37 DportGe = 4,
38 #[doc = "sock.dport <= next_instruction.no (big endian)"]
39 DportLe = 5,
40 #[doc = "check if sock is NOT bound to a port by user,\ni.e. !(sk->userlocks & SOCK_BINDPORT_LOCK)\n"]
41 PortAuto = 6,
42 #[doc = "Check aginst source socket addr packed as hostcond struct (hc),\nfollowed by big-endian ipv4 or ipv6 address (yes, it's that cursed).\n\nThe check equivalent to the following (in order):\n no if hc.port != -1 && hc.port != sock.sport\n yes if hc.family == AF_INET && sock.family == AF_INET6\n && &sock.saddr_u32[0..3] == &[0, 0, 0xffff.to_be()]\n && bits_eq(&sock.saddr_u8[12..], &hc.addr[..], hc.prefix_len)\n no if hc.family != AF_UNSPEC && hc.family != family\n yes if hc.prefix_len == 0\n yes if bits_eq(&sock.addr[..], &hc.addr[..], hc.prefix_len)\n no\n\n See inet_diag_bc_run() in net/ipv4/inet_diag.c\n"]
43 SaddrCond = 7,
44 #[doc = "Check aginst source socket addr using hostcond struct.\nSame as `saddr-cond`, see its description.\n"]
45 DaddrCond = 8,
46 #[doc = "socket ifindex == next_instruction (native endian u32)"]
47 DevCond = 9,
48 #[doc = "Check check socket mark bits against markcond struct (mc).\nThe check is equivalent to: sock.mark & mc.mask == mc.mark\n"]
49 MarkCond = 10,
50 #[doc = "sock.sport == next_instruction.no (big endian)"]
51 SportEq = 11,
52 #[doc = "sock.dport == next_instruction.no (big endian)"]
53 DportEq = 12,
54 #[doc = "sock.cgroup_id == next_2_instructions (native endian u64)"]
55 CgroupCond = 13,
56}
57impl BytecodeOpCode {
58 pub fn from_value(value: u64) -> Option<Self> {
59 Some(match value {
60 0 => Self::Nop,
61 1 => Self::Jmp,
62 2 => Self::SportGe,
63 3 => Self::SportLe,
64 4 => Self::DportGe,
65 5 => Self::DportLe,
66 6 => Self::PortAuto,
67 7 => Self::SaddrCond,
68 8 => Self::DaddrCond,
69 9 => Self::DevCond,
70 10 => Self::MarkCond,
71 11 => Self::SportEq,
72 12 => Self::DportEq,
73 13 => Self::CgroupCond,
74 _ => return None,
75 })
76 }
77}
78#[doc = "Host condition to be placed directly into bytecode.\nSocket address bytes should be appended right after this struct.\n"]
79#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
80#[derive(Debug, Clone, Copy)]
81pub enum SockoptFlag {
82 Recverr = 1 << 0,
83 IsIcsk = 1 << 1,
84 Freebind = 1 << 2,
85 Hdrincl = 1 << 3,
86 McLoop = 1 << 4,
87 Transparent = 1 << 5,
88 McAll = 1 << 6,
89 Nodefrag = 1 << 7,
90 BindAddressNoPort = 1 << 8,
91 RecverrRfc4884 = 1 << 9,
92 DeferConnect = 1 << 10,
93}
94impl SockoptFlag {
95 pub fn from_value(value: u64) -> Option<Self> {
96 Some(match value {
97 n if n == 1 << 0 => Self::Recverr,
98 n if n == 1 << 1 => Self::IsIcsk,
99 n if n == 1 << 2 => Self::Freebind,
100 n if n == 1 << 3 => Self::Hdrincl,
101 n if n == 1 << 4 => Self::McLoop,
102 n if n == 1 << 5 => Self::Transparent,
103 n if n == 1 << 6 => Self::McAll,
104 n if n == 1 << 7 => Self::Nodefrag,
105 n if n == 1 << 8 => Self::BindAddressNoPort,
106 n if n == 1 << 9 => Self::RecverrRfc4884,
107 n if n == 1 << 10 => Self::DeferConnect,
108 _ => return None,
109 })
110 }
111}
112#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
113#[derive(Debug, Clone, Copy)]
114pub enum TcpState {
115 Established = 1,
116 SynSent = 2,
117 SynRecv = 3,
118 FinWait1 = 4,
119 FinWait2 = 5,
120 TimeWait = 6,
121 Close = 7,
122 CloseWait = 8,
123 LastAck = 9,
124 Listen = 10,
125 #[doc = "Now a valid state"]
126 Closing = 11,
127 NewSynRecv = 12,
128 #[doc = "Pseudo-state for inet_diag"]
129 BoundInactive = 13,
130}
131impl TcpState {
132 pub fn from_value(value: u64) -> Option<Self> {
133 Some(match value {
134 1 => Self::Established,
135 2 => Self::SynSent,
136 3 => Self::SynRecv,
137 4 => Self::FinWait1,
138 5 => Self::FinWait2,
139 6 => Self::TimeWait,
140 7 => Self::Close,
141 8 => Self::CloseWait,
142 9 => Self::LastAck,
143 10 => Self::Listen,
144 11 => Self::Closing,
145 12 => Self::NewSynRecv,
146 13 => Self::BoundInactive,
147 _ => return None,
148 })
149 }
150}
151#[derive(Clone)]
152pub enum UlpInfoAttrs<'a> {
153 #[doc = "ULP name (e.g., \"tls\", \"mptcp\")"]
154 Name(&'a CStr),
155 #[doc = "TLS-specific information"]
156 Tls(&'a [u8]),
157 #[doc = "MPTCP-specific information"]
158 Mptcp(&'a [u8]),
159}
160impl<'a> IterableUlpInfoAttrs<'a> {
161 #[doc = "ULP name (e.g., \"tls\", \"mptcp\")"]
162 pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
163 let mut iter = self.clone();
164 iter.pos = 0;
165 for attr in iter {
166 if let UlpInfoAttrs::Name(val) = attr? {
167 return Ok(val);
168 }
169 }
170 Err(ErrorContext::new_missing(
171 "UlpInfoAttrs",
172 "Name",
173 self.orig_loc,
174 self.buf.as_ptr() as usize,
175 ))
176 }
177 #[doc = "TLS-specific information"]
178 pub fn get_tls(&self) -> Result<&'a [u8], ErrorContext> {
179 let mut iter = self.clone();
180 iter.pos = 0;
181 for attr in iter {
182 if let UlpInfoAttrs::Tls(val) = attr? {
183 return Ok(val);
184 }
185 }
186 Err(ErrorContext::new_missing(
187 "UlpInfoAttrs",
188 "Tls",
189 self.orig_loc,
190 self.buf.as_ptr() as usize,
191 ))
192 }
193 #[doc = "MPTCP-specific information"]
194 pub fn get_mptcp(&self) -> Result<&'a [u8], ErrorContext> {
195 let mut iter = self.clone();
196 iter.pos = 0;
197 for attr in iter {
198 if let UlpInfoAttrs::Mptcp(val) = attr? {
199 return Ok(val);
200 }
201 }
202 Err(ErrorContext::new_missing(
203 "UlpInfoAttrs",
204 "Mptcp",
205 self.orig_loc,
206 self.buf.as_ptr() as usize,
207 ))
208 }
209}
210impl UlpInfoAttrs<'_> {
211 pub fn new<'a>(buf: &'a [u8]) -> IterableUlpInfoAttrs<'a> {
212 IterableUlpInfoAttrs::with_loc(buf, buf.as_ptr() as usize)
213 }
214 fn attr_from_type(r#type: u16) -> Option<&'static str> {
215 let res = match r#type {
216 1u16 => "Name",
217 2u16 => "Tls",
218 3u16 => "Mptcp",
219 _ => return None,
220 };
221 Some(res)
222 }
223}
224#[derive(Clone, Copy, Default)]
225pub struct IterableUlpInfoAttrs<'a> {
226 buf: &'a [u8],
227 pos: usize,
228 orig_loc: usize,
229}
230impl<'a> IterableUlpInfoAttrs<'a> {
231 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
232 Self {
233 buf,
234 pos: 0,
235 orig_loc,
236 }
237 }
238 pub fn get_buf(&self) -> &'a [u8] {
239 self.buf
240 }
241}
242impl<'a> Iterator for IterableUlpInfoAttrs<'a> {
243 type Item = Result<UlpInfoAttrs<'a>, ErrorContext>;
244 fn next(&mut self) -> Option<Self::Item> {
245 let pos = self.pos;
246 let mut r#type;
247 loop {
248 r#type = None;
249 if self.buf.len() == self.pos {
250 return None;
251 }
252 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
253 break;
254 };
255 r#type = Some(header.r#type);
256 let res = match header.r#type {
257 1u16 => UlpInfoAttrs::Name({
258 let res = CStr::from_bytes_with_nul(next).ok();
259 let Some(val) = res else { break };
260 val
261 }),
262 2u16 => UlpInfoAttrs::Tls({
263 let res = Some(next);
264 let Some(val) = res else { break };
265 val
266 }),
267 3u16 => UlpInfoAttrs::Mptcp({
268 let res = Some(next);
269 let Some(val) = res else { break };
270 val
271 }),
272 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
273 n => continue,
274 };
275 return Some(Ok(res));
276 }
277 Some(Err(ErrorContext::new(
278 "UlpInfoAttrs",
279 r#type.and_then(|t| UlpInfoAttrs::attr_from_type(t)),
280 self.orig_loc,
281 self.buf.as_ptr().wrapping_add(pos) as usize,
282 )))
283 }
284}
285impl<'a> std::fmt::Debug for IterableUlpInfoAttrs<'_> {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 let mut fmt = f.debug_struct("UlpInfoAttrs");
288 for attr in self.clone() {
289 let attr = match attr {
290 Ok(a) => a,
291 Err(err) => {
292 fmt.finish()?;
293 f.write_str("Err(")?;
294 err.fmt(f)?;
295 return f.write_str(")");
296 }
297 };
298 match attr {
299 UlpInfoAttrs::Name(val) => fmt.field("Name", &val),
300 UlpInfoAttrs::Tls(val) => fmt.field("Tls", &val),
301 UlpInfoAttrs::Mptcp(val) => fmt.field("Mptcp", &val),
302 };
303 }
304 fmt.finish()
305 }
306}
307impl IterableUlpInfoAttrs<'_> {
308 pub fn lookup_attr(
309 &self,
310 offset: usize,
311 missing_type: Option<u16>,
312 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
313 let mut stack = Vec::new();
314 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
315 if cur == offset {
316 stack.push(("UlpInfoAttrs", offset));
317 return (
318 stack,
319 missing_type.and_then(|t| UlpInfoAttrs::attr_from_type(t)),
320 );
321 }
322 if cur > offset || cur + self.buf.len() < offset {
323 return (stack, None);
324 }
325 let mut attrs = self.clone();
326 let mut last_off = cur + attrs.pos;
327 while let Some(attr) = attrs.next() {
328 let Ok(attr) = attr else { break };
329 match attr {
330 UlpInfoAttrs::Name(val) => {
331 if last_off == offset {
332 stack.push(("Name", last_off));
333 break;
334 }
335 }
336 UlpInfoAttrs::Tls(val) => {
337 if last_off == offset {
338 stack.push(("Tls", last_off));
339 break;
340 }
341 }
342 UlpInfoAttrs::Mptcp(val) => {
343 if last_off == offset {
344 stack.push(("Mptcp", last_off));
345 break;
346 }
347 }
348 _ => {}
349 };
350 last_off = cur + attrs.pos;
351 }
352 if !stack.is_empty() {
353 stack.push(("UlpInfoAttrs", cur));
354 }
355 (stack, None)
356 }
357}
358#[derive(Clone)]
359pub enum RequestAttrs<'a> {
360 #[doc = "See bytecode-op"]
361 Bytecode(&'a [u8]),
362 BpfStorages(IterableBpfStorageReq<'a>),
363 Protocol(u32),
364}
365impl<'a> IterableRequestAttrs<'a> {
366 #[doc = "See bytecode-op"]
367 pub fn get_bytecode(&self) -> Result<&'a [u8], ErrorContext> {
368 let mut iter = self.clone();
369 iter.pos = 0;
370 for attr in iter {
371 if let RequestAttrs::Bytecode(val) = attr? {
372 return Ok(val);
373 }
374 }
375 Err(ErrorContext::new_missing(
376 "RequestAttrs",
377 "Bytecode",
378 self.orig_loc,
379 self.buf.as_ptr() as usize,
380 ))
381 }
382 pub fn get_bpf_storages(&self) -> Result<IterableBpfStorageReq<'a>, ErrorContext> {
383 let mut iter = self.clone();
384 iter.pos = 0;
385 for attr in iter {
386 if let RequestAttrs::BpfStorages(val) = attr? {
387 return Ok(val);
388 }
389 }
390 Err(ErrorContext::new_missing(
391 "RequestAttrs",
392 "BpfStorages",
393 self.orig_loc,
394 self.buf.as_ptr() as usize,
395 ))
396 }
397 pub fn get_protocol(&self) -> Result<u32, ErrorContext> {
398 let mut iter = self.clone();
399 iter.pos = 0;
400 for attr in iter {
401 if let RequestAttrs::Protocol(val) = attr? {
402 return Ok(val);
403 }
404 }
405 Err(ErrorContext::new_missing(
406 "RequestAttrs",
407 "Protocol",
408 self.orig_loc,
409 self.buf.as_ptr() as usize,
410 ))
411 }
412}
413impl RequestAttrs<'_> {
414 pub fn new<'a>(buf: &'a [u8]) -> IterableRequestAttrs<'a> {
415 IterableRequestAttrs::with_loc(buf, buf.as_ptr() as usize)
416 }
417 fn attr_from_type(r#type: u16) -> Option<&'static str> {
418 let res = match r#type {
419 1u16 => "Bytecode",
420 2u16 => "BpfStorages",
421 3u16 => "Protocol",
422 _ => return None,
423 };
424 Some(res)
425 }
426}
427#[derive(Clone, Copy, Default)]
428pub struct IterableRequestAttrs<'a> {
429 buf: &'a [u8],
430 pos: usize,
431 orig_loc: usize,
432}
433impl<'a> IterableRequestAttrs<'a> {
434 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
435 Self {
436 buf,
437 pos: 0,
438 orig_loc,
439 }
440 }
441 pub fn get_buf(&self) -> &'a [u8] {
442 self.buf
443 }
444}
445impl<'a> Iterator for IterableRequestAttrs<'a> {
446 type Item = Result<RequestAttrs<'a>, ErrorContext>;
447 fn next(&mut self) -> Option<Self::Item> {
448 let pos = self.pos;
449 let mut r#type;
450 loop {
451 r#type = None;
452 if self.buf.len() == self.pos {
453 return None;
454 }
455 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
456 break;
457 };
458 r#type = Some(header.r#type);
459 let res = match header.r#type {
460 1u16 => RequestAttrs::Bytecode({
461 let res = Some(next);
462 let Some(val) = res else { break };
463 val
464 }),
465 2u16 => RequestAttrs::BpfStorages({
466 let res = Some(IterableBpfStorageReq::with_loc(next, self.orig_loc));
467 let Some(val) = res else { break };
468 val
469 }),
470 3u16 => RequestAttrs::Protocol({
471 let res = parse_u32(next);
472 let Some(val) = res else { break };
473 val
474 }),
475 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
476 n => continue,
477 };
478 return Some(Ok(res));
479 }
480 Some(Err(ErrorContext::new(
481 "RequestAttrs",
482 r#type.and_then(|t| RequestAttrs::attr_from_type(t)),
483 self.orig_loc,
484 self.buf.as_ptr().wrapping_add(pos) as usize,
485 )))
486 }
487}
488impl<'a> std::fmt::Debug for IterableRequestAttrs<'_> {
489 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
490 let mut fmt = f.debug_struct("RequestAttrs");
491 for attr in self.clone() {
492 let attr = match attr {
493 Ok(a) => a,
494 Err(err) => {
495 fmt.finish()?;
496 f.write_str("Err(")?;
497 err.fmt(f)?;
498 return f.write_str(")");
499 }
500 };
501 match attr {
502 RequestAttrs::Bytecode(val) => {
503 let iter = val
504 .chunks(BytecodeOp::len())
505 .map(|b| BytecodeOp::new_from_zeroed(b));
506 fmt.field("Bytecode", &FormatIter(iter))
507 }
508 RequestAttrs::BpfStorages(val) => fmt.field("BpfStorages", &val),
509 RequestAttrs::Protocol(val) => fmt.field("Protocol", &val),
510 };
511 }
512 fmt.finish()
513 }
514}
515impl IterableRequestAttrs<'_> {
516 pub fn lookup_attr(
517 &self,
518 offset: usize,
519 missing_type: Option<u16>,
520 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
521 let mut stack = Vec::new();
522 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
523 if cur == offset {
524 stack.push(("RequestAttrs", offset));
525 return (
526 stack,
527 missing_type.and_then(|t| RequestAttrs::attr_from_type(t)),
528 );
529 }
530 if cur > offset || cur + self.buf.len() < offset {
531 return (stack, None);
532 }
533 let mut attrs = self.clone();
534 let mut last_off = cur + attrs.pos;
535 let mut missing = None;
536 while let Some(attr) = attrs.next() {
537 let Ok(attr) = attr else { break };
538 match attr {
539 RequestAttrs::Bytecode(val) => {
540 if last_off == offset {
541 stack.push(("Bytecode", last_off));
542 break;
543 }
544 }
545 RequestAttrs::BpfStorages(val) => {
546 (stack, missing) = val.lookup_attr(offset, missing_type);
547 if !stack.is_empty() {
548 break;
549 }
550 }
551 RequestAttrs::Protocol(val) => {
552 if last_off == offset {
553 stack.push(("Protocol", last_off));
554 break;
555 }
556 }
557 _ => {}
558 };
559 last_off = cur + attrs.pos;
560 }
561 if !stack.is_empty() {
562 stack.push(("RequestAttrs", cur));
563 }
564 (stack, missing)
565 }
566}
567#[derive(Clone)]
568pub enum ReplyAttrs<'a> {
569 #[doc = "Memory information extension"]
570 Meminfo(Meminfo),
571 TcpInfo(TcpInfo),
572 #[doc = "TCP Vegas information"]
573 Vegasinfo(TcpvegasInfo),
574 #[doc = "Congestion control algorithm name"]
575 Cong(&'a CStr),
576 #[doc = "Type of Service"]
577 Tos(u8),
578 #[doc = "Traffic Class"]
579 Tclass(u8),
580 #[doc = "Socket memory information"]
581 Skmeminfo(&'a [u8]),
582 #[doc = "Shutdown state"]
583 Shutdown(u8),
584 #[doc = "TCP DCTCP information (request as INET_DIAG_VEGASINFO)"]
585 Dctcpinfo(TcpDctcpInfo),
586 #[doc = "Raw socket protocol (response attribute only)"]
587 Protocol(u8),
588 #[doc = "IPv6-only socket flag"]
589 Skv6only(()),
590 #[doc = "Local addresses. SCTP thing."]
591 Locals(&'a [u8]),
592 #[doc = "Peer addresses. SCTP thing."]
593 Peers(&'a [u8]),
594 Pad(&'a [u8]),
595 #[doc = "Socket mark (only with CAP_NET_ADMIN)"]
596 Mark(u32),
597 #[doc = "TCP BBR information (request as INET_DIAG_VEGASINFO)"]
598 Bbritfo(TcpBbrInfo),
599 #[doc = "Class ID (request as INET_DIAG_TCLASS)"]
600 ClassId(u32),
601 #[doc = "MD5 signature information"]
602 Md5sig(&'a [u8]),
603 #[doc = "Upper Layer Protocol information"]
604 UlpInfo(IterableUlpInfoAttrs<'a>),
605 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
606 SkBpfStorages(IterableBpfStorageReply<'a>),
607 #[doc = "Cgroup ID"]
608 CgroupId(u64),
609 #[doc = "Socket options\nAssociated type: \"SockoptFlag\" (enum)"]
610 SockoptFlags(u16),
611}
612impl<'a> IterableReplyAttrs<'a> {
613 #[doc = "Memory information extension"]
614 pub fn get_meminfo(&self) -> Result<Meminfo, ErrorContext> {
615 let mut iter = self.clone();
616 iter.pos = 0;
617 for attr in iter {
618 if let ReplyAttrs::Meminfo(val) = attr? {
619 return Ok(val);
620 }
621 }
622 Err(ErrorContext::new_missing(
623 "ReplyAttrs",
624 "Meminfo",
625 self.orig_loc,
626 self.buf.as_ptr() as usize,
627 ))
628 }
629 pub fn get_tcp_info(&self) -> Result<TcpInfo, ErrorContext> {
630 let mut iter = self.clone();
631 iter.pos = 0;
632 for attr in iter {
633 if let ReplyAttrs::TcpInfo(val) = attr? {
634 return Ok(val);
635 }
636 }
637 Err(ErrorContext::new_missing(
638 "ReplyAttrs",
639 "TcpInfo",
640 self.orig_loc,
641 self.buf.as_ptr() as usize,
642 ))
643 }
644 #[doc = "TCP Vegas information"]
645 pub fn get_vegasinfo(&self) -> Result<TcpvegasInfo, ErrorContext> {
646 let mut iter = self.clone();
647 iter.pos = 0;
648 for attr in iter {
649 if let ReplyAttrs::Vegasinfo(val) = attr? {
650 return Ok(val);
651 }
652 }
653 Err(ErrorContext::new_missing(
654 "ReplyAttrs",
655 "Vegasinfo",
656 self.orig_loc,
657 self.buf.as_ptr() as usize,
658 ))
659 }
660 #[doc = "Congestion control algorithm name"]
661 pub fn get_cong(&self) -> Result<&'a CStr, ErrorContext> {
662 let mut iter = self.clone();
663 iter.pos = 0;
664 for attr in iter {
665 if let ReplyAttrs::Cong(val) = attr? {
666 return Ok(val);
667 }
668 }
669 Err(ErrorContext::new_missing(
670 "ReplyAttrs",
671 "Cong",
672 self.orig_loc,
673 self.buf.as_ptr() as usize,
674 ))
675 }
676 #[doc = "Type of Service"]
677 pub fn get_tos(&self) -> Result<u8, ErrorContext> {
678 let mut iter = self.clone();
679 iter.pos = 0;
680 for attr in iter {
681 if let ReplyAttrs::Tos(val) = attr? {
682 return Ok(val);
683 }
684 }
685 Err(ErrorContext::new_missing(
686 "ReplyAttrs",
687 "Tos",
688 self.orig_loc,
689 self.buf.as_ptr() as usize,
690 ))
691 }
692 #[doc = "Traffic Class"]
693 pub fn get_tclass(&self) -> Result<u8, ErrorContext> {
694 let mut iter = self.clone();
695 iter.pos = 0;
696 for attr in iter {
697 if let ReplyAttrs::Tclass(val) = attr? {
698 return Ok(val);
699 }
700 }
701 Err(ErrorContext::new_missing(
702 "ReplyAttrs",
703 "Tclass",
704 self.orig_loc,
705 self.buf.as_ptr() as usize,
706 ))
707 }
708 #[doc = "Socket memory information"]
709 pub fn get_skmeminfo(&self) -> Result<&'a [u8], ErrorContext> {
710 let mut iter = self.clone();
711 iter.pos = 0;
712 for attr in iter {
713 if let ReplyAttrs::Skmeminfo(val) = attr? {
714 return Ok(val);
715 }
716 }
717 Err(ErrorContext::new_missing(
718 "ReplyAttrs",
719 "Skmeminfo",
720 self.orig_loc,
721 self.buf.as_ptr() as usize,
722 ))
723 }
724 #[doc = "Shutdown state"]
725 pub fn get_shutdown(&self) -> Result<u8, ErrorContext> {
726 let mut iter = self.clone();
727 iter.pos = 0;
728 for attr in iter {
729 if let ReplyAttrs::Shutdown(val) = attr? {
730 return Ok(val);
731 }
732 }
733 Err(ErrorContext::new_missing(
734 "ReplyAttrs",
735 "Shutdown",
736 self.orig_loc,
737 self.buf.as_ptr() as usize,
738 ))
739 }
740 #[doc = "TCP DCTCP information (request as INET_DIAG_VEGASINFO)"]
741 pub fn get_dctcpinfo(&self) -> Result<TcpDctcpInfo, ErrorContext> {
742 let mut iter = self.clone();
743 iter.pos = 0;
744 for attr in iter {
745 if let ReplyAttrs::Dctcpinfo(val) = attr? {
746 return Ok(val);
747 }
748 }
749 Err(ErrorContext::new_missing(
750 "ReplyAttrs",
751 "Dctcpinfo",
752 self.orig_loc,
753 self.buf.as_ptr() as usize,
754 ))
755 }
756 #[doc = "Raw socket protocol (response attribute only)"]
757 pub fn get_protocol(&self) -> Result<u8, ErrorContext> {
758 let mut iter = self.clone();
759 iter.pos = 0;
760 for attr in iter {
761 if let ReplyAttrs::Protocol(val) = attr? {
762 return Ok(val);
763 }
764 }
765 Err(ErrorContext::new_missing(
766 "ReplyAttrs",
767 "Protocol",
768 self.orig_loc,
769 self.buf.as_ptr() as usize,
770 ))
771 }
772 #[doc = "IPv6-only socket flag"]
773 pub fn get_skv6only(&self) -> Result<(), ErrorContext> {
774 let mut iter = self.clone();
775 iter.pos = 0;
776 for attr in iter {
777 if let ReplyAttrs::Skv6only(val) = attr? {
778 return Ok(val);
779 }
780 }
781 Err(ErrorContext::new_missing(
782 "ReplyAttrs",
783 "Skv6only",
784 self.orig_loc,
785 self.buf.as_ptr() as usize,
786 ))
787 }
788 #[doc = "Local addresses. SCTP thing."]
789 pub fn get_locals(&self) -> Result<&'a [u8], ErrorContext> {
790 let mut iter = self.clone();
791 iter.pos = 0;
792 for attr in iter {
793 if let ReplyAttrs::Locals(val) = attr? {
794 return Ok(val);
795 }
796 }
797 Err(ErrorContext::new_missing(
798 "ReplyAttrs",
799 "Locals",
800 self.orig_loc,
801 self.buf.as_ptr() as usize,
802 ))
803 }
804 #[doc = "Peer addresses. SCTP thing."]
805 pub fn get_peers(&self) -> Result<&'a [u8], ErrorContext> {
806 let mut iter = self.clone();
807 iter.pos = 0;
808 for attr in iter {
809 if let ReplyAttrs::Peers(val) = attr? {
810 return Ok(val);
811 }
812 }
813 Err(ErrorContext::new_missing(
814 "ReplyAttrs",
815 "Peers",
816 self.orig_loc,
817 self.buf.as_ptr() as usize,
818 ))
819 }
820 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
821 let mut iter = self.clone();
822 iter.pos = 0;
823 for attr in iter {
824 if let ReplyAttrs::Pad(val) = attr? {
825 return Ok(val);
826 }
827 }
828 Err(ErrorContext::new_missing(
829 "ReplyAttrs",
830 "Pad",
831 self.orig_loc,
832 self.buf.as_ptr() as usize,
833 ))
834 }
835 #[doc = "Socket mark (only with CAP_NET_ADMIN)"]
836 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
837 let mut iter = self.clone();
838 iter.pos = 0;
839 for attr in iter {
840 if let ReplyAttrs::Mark(val) = attr? {
841 return Ok(val);
842 }
843 }
844 Err(ErrorContext::new_missing(
845 "ReplyAttrs",
846 "Mark",
847 self.orig_loc,
848 self.buf.as_ptr() as usize,
849 ))
850 }
851 #[doc = "TCP BBR information (request as INET_DIAG_VEGASINFO)"]
852 pub fn get_bbritfo(&self) -> Result<TcpBbrInfo, ErrorContext> {
853 let mut iter = self.clone();
854 iter.pos = 0;
855 for attr in iter {
856 if let ReplyAttrs::Bbritfo(val) = attr? {
857 return Ok(val);
858 }
859 }
860 Err(ErrorContext::new_missing(
861 "ReplyAttrs",
862 "Bbritfo",
863 self.orig_loc,
864 self.buf.as_ptr() as usize,
865 ))
866 }
867 #[doc = "Class ID (request as INET_DIAG_TCLASS)"]
868 pub fn get_class_id(&self) -> Result<u32, ErrorContext> {
869 let mut iter = self.clone();
870 iter.pos = 0;
871 for attr in iter {
872 if let ReplyAttrs::ClassId(val) = attr? {
873 return Ok(val);
874 }
875 }
876 Err(ErrorContext::new_missing(
877 "ReplyAttrs",
878 "ClassId",
879 self.orig_loc,
880 self.buf.as_ptr() as usize,
881 ))
882 }
883 #[doc = "MD5 signature information"]
884 pub fn get_md5sig(&self) -> Result<&'a [u8], ErrorContext> {
885 let mut iter = self.clone();
886 iter.pos = 0;
887 for attr in iter {
888 if let ReplyAttrs::Md5sig(val) = attr? {
889 return Ok(val);
890 }
891 }
892 Err(ErrorContext::new_missing(
893 "ReplyAttrs",
894 "Md5sig",
895 self.orig_loc,
896 self.buf.as_ptr() as usize,
897 ))
898 }
899 #[doc = "Upper Layer Protocol information"]
900 pub fn get_ulp_info(&self) -> Result<IterableUlpInfoAttrs<'a>, ErrorContext> {
901 let mut iter = self.clone();
902 iter.pos = 0;
903 for attr in iter {
904 if let ReplyAttrs::UlpInfo(val) = attr? {
905 return Ok(val);
906 }
907 }
908 Err(ErrorContext::new_missing(
909 "ReplyAttrs",
910 "UlpInfo",
911 self.orig_loc,
912 self.buf.as_ptr() as usize,
913 ))
914 }
915 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
916 pub fn get_sk_bpf_storages(
917 &self,
918 ) -> MultiAttrIterable<Self, ReplyAttrs<'a>, IterableBpfStorageReply<'a>> {
919 MultiAttrIterable::new(self.clone(), |variant| {
920 if let ReplyAttrs::SkBpfStorages(val) = variant {
921 Some(val)
922 } else {
923 None
924 }
925 })
926 }
927 #[doc = "Cgroup ID"]
928 pub fn get_cgroup_id(&self) -> Result<u64, ErrorContext> {
929 let mut iter = self.clone();
930 iter.pos = 0;
931 for attr in iter {
932 if let ReplyAttrs::CgroupId(val) = attr? {
933 return Ok(val);
934 }
935 }
936 Err(ErrorContext::new_missing(
937 "ReplyAttrs",
938 "CgroupId",
939 self.orig_loc,
940 self.buf.as_ptr() as usize,
941 ))
942 }
943 #[doc = "Socket options\nAssociated type: \"SockoptFlag\" (enum)"]
944 pub fn get_sockopt_flags(&self) -> Result<u16, ErrorContext> {
945 let mut iter = self.clone();
946 iter.pos = 0;
947 for attr in iter {
948 if let ReplyAttrs::SockoptFlags(val) = attr? {
949 return Ok(val);
950 }
951 }
952 Err(ErrorContext::new_missing(
953 "ReplyAttrs",
954 "SockoptFlags",
955 self.orig_loc,
956 self.buf.as_ptr() as usize,
957 ))
958 }
959}
960impl ReplyAttrs<'_> {
961 pub fn new<'a>(buf: &'a [u8]) -> IterableReplyAttrs<'a> {
962 IterableReplyAttrs::with_loc(buf, buf.as_ptr() as usize)
963 }
964 fn attr_from_type(r#type: u16) -> Option<&'static str> {
965 let res = match r#type {
966 1u16 => "Meminfo",
967 2u16 => "TcpInfo",
968 3u16 => "Vegasinfo",
969 4u16 => "Cong",
970 5u16 => "Tos",
971 6u16 => "Tclass",
972 7u16 => "Skmeminfo",
973 8u16 => "Shutdown",
974 9u16 => "Dctcpinfo",
975 10u16 => "Protocol",
976 11u16 => "Skv6only",
977 12u16 => "Locals",
978 13u16 => "Peers",
979 14u16 => "Pad",
980 15u16 => "Mark",
981 16u16 => "Bbritfo",
982 17u16 => "ClassId",
983 18u16 => "Md5sig",
984 19u16 => "UlpInfo",
985 20u16 => "SkBpfStorages",
986 21u16 => "CgroupId",
987 22u16 => "SockoptFlags",
988 _ => return None,
989 };
990 Some(res)
991 }
992}
993#[derive(Clone, Copy, Default)]
994pub struct IterableReplyAttrs<'a> {
995 buf: &'a [u8],
996 pos: usize,
997 orig_loc: usize,
998}
999impl<'a> IterableReplyAttrs<'a> {
1000 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1001 Self {
1002 buf,
1003 pos: 0,
1004 orig_loc,
1005 }
1006 }
1007 pub fn get_buf(&self) -> &'a [u8] {
1008 self.buf
1009 }
1010}
1011impl<'a> Iterator for IterableReplyAttrs<'a> {
1012 type Item = Result<ReplyAttrs<'a>, ErrorContext>;
1013 fn next(&mut self) -> Option<Self::Item> {
1014 let pos = self.pos;
1015 let mut r#type;
1016 loop {
1017 r#type = None;
1018 if self.buf.len() == self.pos {
1019 return None;
1020 }
1021 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1022 break;
1023 };
1024 r#type = Some(header.r#type);
1025 let res = match header.r#type {
1026 1u16 => ReplyAttrs::Meminfo({
1027 let res = Meminfo::new_from_slice(next);
1028 let Some(val) = res else { break };
1029 val
1030 }),
1031 2u16 => ReplyAttrs::TcpInfo({
1032 let res = TcpInfo::new_from_slice(next);
1033 let Some(val) = res else { break };
1034 val
1035 }),
1036 3u16 => ReplyAttrs::Vegasinfo({
1037 let res = TcpvegasInfo::new_from_slice(next);
1038 let Some(val) = res else { break };
1039 val
1040 }),
1041 4u16 => ReplyAttrs::Cong({
1042 let res = CStr::from_bytes_with_nul(next).ok();
1043 let Some(val) = res else { break };
1044 val
1045 }),
1046 5u16 => ReplyAttrs::Tos({
1047 let res = parse_u8(next);
1048 let Some(val) = res else { break };
1049 val
1050 }),
1051 6u16 => ReplyAttrs::Tclass({
1052 let res = parse_u8(next);
1053 let Some(val) = res else { break };
1054 val
1055 }),
1056 7u16 => ReplyAttrs::Skmeminfo({
1057 let res = Some(next);
1058 let Some(val) = res else { break };
1059 val
1060 }),
1061 8u16 => ReplyAttrs::Shutdown({
1062 let res = parse_u8(next);
1063 let Some(val) = res else { break };
1064 val
1065 }),
1066 9u16 => ReplyAttrs::Dctcpinfo({
1067 let res = TcpDctcpInfo::new_from_slice(next);
1068 let Some(val) = res else { break };
1069 val
1070 }),
1071 10u16 => ReplyAttrs::Protocol({
1072 let res = parse_u8(next);
1073 let Some(val) = res else { break };
1074 val
1075 }),
1076 11u16 => ReplyAttrs::Skv6only(()),
1077 12u16 => ReplyAttrs::Locals({
1078 let res = Some(next);
1079 let Some(val) = res else { break };
1080 val
1081 }),
1082 13u16 => ReplyAttrs::Peers({
1083 let res = Some(next);
1084 let Some(val) = res else { break };
1085 val
1086 }),
1087 14u16 => ReplyAttrs::Pad({
1088 let res = Some(next);
1089 let Some(val) = res else { break };
1090 val
1091 }),
1092 15u16 => ReplyAttrs::Mark({
1093 let res = parse_u32(next);
1094 let Some(val) = res else { break };
1095 val
1096 }),
1097 16u16 => ReplyAttrs::Bbritfo({
1098 let res = TcpBbrInfo::new_from_slice(next);
1099 let Some(val) = res else { break };
1100 val
1101 }),
1102 17u16 => ReplyAttrs::ClassId({
1103 let res = parse_u32(next);
1104 let Some(val) = res else { break };
1105 val
1106 }),
1107 18u16 => ReplyAttrs::Md5sig({
1108 let res = Some(next);
1109 let Some(val) = res else { break };
1110 val
1111 }),
1112 19u16 => ReplyAttrs::UlpInfo({
1113 let res = Some(IterableUlpInfoAttrs::with_loc(next, self.orig_loc));
1114 let Some(val) = res else { break };
1115 val
1116 }),
1117 20u16 => ReplyAttrs::SkBpfStorages({
1118 let res = Some(IterableBpfStorageReply::with_loc(next, self.orig_loc));
1119 let Some(val) = res else { break };
1120 val
1121 }),
1122 21u16 => ReplyAttrs::CgroupId({
1123 let res = parse_u64(next);
1124 let Some(val) = res else { break };
1125 val
1126 }),
1127 22u16 => ReplyAttrs::SockoptFlags({
1128 let res = parse_u16(next);
1129 let Some(val) = res else { break };
1130 val
1131 }),
1132 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1133 n => continue,
1134 };
1135 return Some(Ok(res));
1136 }
1137 Some(Err(ErrorContext::new(
1138 "ReplyAttrs",
1139 r#type.and_then(|t| ReplyAttrs::attr_from_type(t)),
1140 self.orig_loc,
1141 self.buf.as_ptr().wrapping_add(pos) as usize,
1142 )))
1143 }
1144}
1145impl<'a> std::fmt::Debug for IterableReplyAttrs<'_> {
1146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1147 let mut fmt = f.debug_struct("ReplyAttrs");
1148 for attr in self.clone() {
1149 let attr = match attr {
1150 Ok(a) => a,
1151 Err(err) => {
1152 fmt.finish()?;
1153 f.write_str("Err(")?;
1154 err.fmt(f)?;
1155 return f.write_str(")");
1156 }
1157 };
1158 match attr {
1159 ReplyAttrs::Meminfo(val) => fmt.field("Meminfo", &val),
1160 ReplyAttrs::TcpInfo(val) => fmt.field("TcpInfo", &val),
1161 ReplyAttrs::Vegasinfo(val) => fmt.field("Vegasinfo", &val),
1162 ReplyAttrs::Cong(val) => fmt.field("Cong", &val),
1163 ReplyAttrs::Tos(val) => fmt.field("Tos", &val),
1164 ReplyAttrs::Tclass(val) => fmt.field("Tclass", &val),
1165 ReplyAttrs::Skmeminfo(val) => fmt.field("Skmeminfo", &val),
1166 ReplyAttrs::Shutdown(val) => fmt.field("Shutdown", &val),
1167 ReplyAttrs::Dctcpinfo(val) => fmt.field("Dctcpinfo", &val),
1168 ReplyAttrs::Protocol(val) => fmt.field("Protocol", &val),
1169 ReplyAttrs::Skv6only(val) => fmt.field("Skv6only", &val),
1170 ReplyAttrs::Locals(val) => fmt.field("Locals", &val),
1171 ReplyAttrs::Peers(val) => fmt.field("Peers", &val),
1172 ReplyAttrs::Pad(val) => fmt.field("Pad", &val),
1173 ReplyAttrs::Mark(val) => fmt.field("Mark", &val),
1174 ReplyAttrs::Bbritfo(val) => fmt.field("Bbritfo", &val),
1175 ReplyAttrs::ClassId(val) => fmt.field("ClassId", &val),
1176 ReplyAttrs::Md5sig(val) => fmt.field("Md5sig", &val),
1177 ReplyAttrs::UlpInfo(val) => fmt.field("UlpInfo", &val),
1178 ReplyAttrs::SkBpfStorages(val) => fmt.field("SkBpfStorages", &val),
1179 ReplyAttrs::CgroupId(val) => fmt.field("CgroupId", &val),
1180 ReplyAttrs::SockoptFlags(val) => fmt.field(
1181 "SockoptFlags",
1182 &FormatFlags(val.into(), SockoptFlag::from_value),
1183 ),
1184 };
1185 }
1186 fmt.finish()
1187 }
1188}
1189impl IterableReplyAttrs<'_> {
1190 pub fn lookup_attr(
1191 &self,
1192 offset: usize,
1193 missing_type: Option<u16>,
1194 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1195 let mut stack = Vec::new();
1196 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1197 if cur == offset {
1198 stack.push(("ReplyAttrs", offset));
1199 return (
1200 stack,
1201 missing_type.and_then(|t| ReplyAttrs::attr_from_type(t)),
1202 );
1203 }
1204 if cur > offset || cur + self.buf.len() < offset {
1205 return (stack, None);
1206 }
1207 let mut attrs = self.clone();
1208 let mut last_off = cur + attrs.pos;
1209 let mut missing = None;
1210 while let Some(attr) = attrs.next() {
1211 let Ok(attr) = attr else { break };
1212 match attr {
1213 ReplyAttrs::Meminfo(val) => {
1214 if last_off == offset {
1215 stack.push(("Meminfo", last_off));
1216 break;
1217 }
1218 }
1219 ReplyAttrs::TcpInfo(val) => {
1220 if last_off == offset {
1221 stack.push(("TcpInfo", last_off));
1222 break;
1223 }
1224 }
1225 ReplyAttrs::Vegasinfo(val) => {
1226 if last_off == offset {
1227 stack.push(("Vegasinfo", last_off));
1228 break;
1229 }
1230 }
1231 ReplyAttrs::Cong(val) => {
1232 if last_off == offset {
1233 stack.push(("Cong", last_off));
1234 break;
1235 }
1236 }
1237 ReplyAttrs::Tos(val) => {
1238 if last_off == offset {
1239 stack.push(("Tos", last_off));
1240 break;
1241 }
1242 }
1243 ReplyAttrs::Tclass(val) => {
1244 if last_off == offset {
1245 stack.push(("Tclass", last_off));
1246 break;
1247 }
1248 }
1249 ReplyAttrs::Skmeminfo(val) => {
1250 if last_off == offset {
1251 stack.push(("Skmeminfo", last_off));
1252 break;
1253 }
1254 }
1255 ReplyAttrs::Shutdown(val) => {
1256 if last_off == offset {
1257 stack.push(("Shutdown", last_off));
1258 break;
1259 }
1260 }
1261 ReplyAttrs::Dctcpinfo(val) => {
1262 if last_off == offset {
1263 stack.push(("Dctcpinfo", last_off));
1264 break;
1265 }
1266 }
1267 ReplyAttrs::Protocol(val) => {
1268 if last_off == offset {
1269 stack.push(("Protocol", last_off));
1270 break;
1271 }
1272 }
1273 ReplyAttrs::Skv6only(val) => {
1274 if last_off == offset {
1275 stack.push(("Skv6only", last_off));
1276 break;
1277 }
1278 }
1279 ReplyAttrs::Locals(val) => {
1280 if last_off == offset {
1281 stack.push(("Locals", last_off));
1282 break;
1283 }
1284 }
1285 ReplyAttrs::Peers(val) => {
1286 if last_off == offset {
1287 stack.push(("Peers", last_off));
1288 break;
1289 }
1290 }
1291 ReplyAttrs::Pad(val) => {
1292 if last_off == offset {
1293 stack.push(("Pad", last_off));
1294 break;
1295 }
1296 }
1297 ReplyAttrs::Mark(val) => {
1298 if last_off == offset {
1299 stack.push(("Mark", last_off));
1300 break;
1301 }
1302 }
1303 ReplyAttrs::Bbritfo(val) => {
1304 if last_off == offset {
1305 stack.push(("Bbritfo", last_off));
1306 break;
1307 }
1308 }
1309 ReplyAttrs::ClassId(val) => {
1310 if last_off == offset {
1311 stack.push(("ClassId", last_off));
1312 break;
1313 }
1314 }
1315 ReplyAttrs::Md5sig(val) => {
1316 if last_off == offset {
1317 stack.push(("Md5sig", last_off));
1318 break;
1319 }
1320 }
1321 ReplyAttrs::UlpInfo(val) => {
1322 (stack, missing) = val.lookup_attr(offset, missing_type);
1323 if !stack.is_empty() {
1324 break;
1325 }
1326 }
1327 ReplyAttrs::SkBpfStorages(val) => {
1328 (stack, missing) = val.lookup_attr(offset, missing_type);
1329 if !stack.is_empty() {
1330 break;
1331 }
1332 }
1333 ReplyAttrs::CgroupId(val) => {
1334 if last_off == offset {
1335 stack.push(("CgroupId", last_off));
1336 break;
1337 }
1338 }
1339 ReplyAttrs::SockoptFlags(val) => {
1340 if last_off == offset {
1341 stack.push(("SockoptFlags", last_off));
1342 break;
1343 }
1344 }
1345 _ => {}
1346 };
1347 last_off = cur + attrs.pos;
1348 }
1349 if !stack.is_empty() {
1350 stack.push(("ReplyAttrs", cur));
1351 }
1352 (stack, missing)
1353 }
1354}
1355#[derive(Clone)]
1356pub enum BpfStorageReq {
1357 #[doc = "Attribute may repeat multiple times (treat it as array)"]
1358 MapFd(u32),
1359}
1360impl<'a> IterableBpfStorageReq<'a> {
1361 #[doc = "Attribute may repeat multiple times (treat it as array)"]
1362 pub fn get_map_fd(&self) -> MultiAttrIterable<Self, BpfStorageReq, u32> {
1363 MultiAttrIterable::new(self.clone(), |variant| {
1364 if let BpfStorageReq::MapFd(val) = variant {
1365 Some(val)
1366 } else {
1367 None
1368 }
1369 })
1370 }
1371}
1372impl BpfStorageReq {
1373 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorageReq<'a> {
1374 IterableBpfStorageReq::with_loc(buf, buf.as_ptr() as usize)
1375 }
1376 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1377 let res = match r#type {
1378 1u16 => "MapFd",
1379 _ => return None,
1380 };
1381 Some(res)
1382 }
1383}
1384#[derive(Clone, Copy, Default)]
1385pub struct IterableBpfStorageReq<'a> {
1386 buf: &'a [u8],
1387 pos: usize,
1388 orig_loc: usize,
1389}
1390impl<'a> IterableBpfStorageReq<'a> {
1391 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1392 Self {
1393 buf,
1394 pos: 0,
1395 orig_loc,
1396 }
1397 }
1398 pub fn get_buf(&self) -> &'a [u8] {
1399 self.buf
1400 }
1401}
1402impl<'a> Iterator for IterableBpfStorageReq<'a> {
1403 type Item = Result<BpfStorageReq, ErrorContext>;
1404 fn next(&mut self) -> Option<Self::Item> {
1405 let pos = self.pos;
1406 let mut r#type;
1407 loop {
1408 r#type = None;
1409 if self.buf.len() == self.pos {
1410 return None;
1411 }
1412 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1413 break;
1414 };
1415 r#type = Some(header.r#type);
1416 let res = match header.r#type {
1417 1u16 => BpfStorageReq::MapFd({
1418 let res = parse_u32(next);
1419 let Some(val) = res else { break };
1420 val
1421 }),
1422 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1423 n => continue,
1424 };
1425 return Some(Ok(res));
1426 }
1427 Some(Err(ErrorContext::new(
1428 "BpfStorageReq",
1429 r#type.and_then(|t| BpfStorageReq::attr_from_type(t)),
1430 self.orig_loc,
1431 self.buf.as_ptr().wrapping_add(pos) as usize,
1432 )))
1433 }
1434}
1435impl std::fmt::Debug for IterableBpfStorageReq<'_> {
1436 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1437 let mut fmt = f.debug_struct("BpfStorageReq");
1438 for attr in self.clone() {
1439 let attr = match attr {
1440 Ok(a) => a,
1441 Err(err) => {
1442 fmt.finish()?;
1443 f.write_str("Err(")?;
1444 err.fmt(f)?;
1445 return f.write_str(")");
1446 }
1447 };
1448 match attr {
1449 BpfStorageReq::MapFd(val) => fmt.field("MapFd", &val),
1450 };
1451 }
1452 fmt.finish()
1453 }
1454}
1455impl IterableBpfStorageReq<'_> {
1456 pub fn lookup_attr(
1457 &self,
1458 offset: usize,
1459 missing_type: Option<u16>,
1460 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1461 let mut stack = Vec::new();
1462 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1463 if cur == offset {
1464 stack.push(("BpfStorageReq", offset));
1465 return (
1466 stack,
1467 missing_type.and_then(|t| BpfStorageReq::attr_from_type(t)),
1468 );
1469 }
1470 if cur > offset || cur + self.buf.len() < offset {
1471 return (stack, None);
1472 }
1473 let mut attrs = self.clone();
1474 let mut last_off = cur + attrs.pos;
1475 while let Some(attr) = attrs.next() {
1476 let Ok(attr) = attr else { break };
1477 match attr {
1478 BpfStorageReq::MapFd(val) => {
1479 if last_off == offset {
1480 stack.push(("MapFd", last_off));
1481 break;
1482 }
1483 }
1484 _ => {}
1485 };
1486 last_off = cur + attrs.pos;
1487 }
1488 if !stack.is_empty() {
1489 stack.push(("BpfStorageReq", cur));
1490 }
1491 (stack, None)
1492 }
1493}
1494#[derive(Clone)]
1495pub enum BpfStorageReply<'a> {
1496 Storage(IterableBpfStorage<'a>),
1497}
1498impl<'a> IterableBpfStorageReply<'a> {
1499 pub fn get_storage(&self) -> Result<IterableBpfStorage<'a>, ErrorContext> {
1500 let mut iter = self.clone();
1501 iter.pos = 0;
1502 for attr in iter {
1503 if let BpfStorageReply::Storage(val) = attr? {
1504 return Ok(val);
1505 }
1506 }
1507 Err(ErrorContext::new_missing(
1508 "BpfStorageReply",
1509 "Storage",
1510 self.orig_loc,
1511 self.buf.as_ptr() as usize,
1512 ))
1513 }
1514}
1515impl BpfStorageReply<'_> {
1516 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorageReply<'a> {
1517 IterableBpfStorageReply::with_loc(buf, buf.as_ptr() as usize)
1518 }
1519 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1520 let res = match r#type {
1521 1u16 => "Storage",
1522 _ => return None,
1523 };
1524 Some(res)
1525 }
1526}
1527#[derive(Clone, Copy, Default)]
1528pub struct IterableBpfStorageReply<'a> {
1529 buf: &'a [u8],
1530 pos: usize,
1531 orig_loc: usize,
1532}
1533impl<'a> IterableBpfStorageReply<'a> {
1534 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1535 Self {
1536 buf,
1537 pos: 0,
1538 orig_loc,
1539 }
1540 }
1541 pub fn get_buf(&self) -> &'a [u8] {
1542 self.buf
1543 }
1544}
1545impl<'a> Iterator for IterableBpfStorageReply<'a> {
1546 type Item = Result<BpfStorageReply<'a>, ErrorContext>;
1547 fn next(&mut self) -> Option<Self::Item> {
1548 let pos = self.pos;
1549 let mut r#type;
1550 loop {
1551 r#type = None;
1552 if self.buf.len() == self.pos {
1553 return None;
1554 }
1555 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1556 break;
1557 };
1558 r#type = Some(header.r#type);
1559 let res = match header.r#type {
1560 1u16 => BpfStorageReply::Storage({
1561 let res = Some(IterableBpfStorage::with_loc(next, self.orig_loc));
1562 let Some(val) = res else { break };
1563 val
1564 }),
1565 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1566 n => continue,
1567 };
1568 return Some(Ok(res));
1569 }
1570 Some(Err(ErrorContext::new(
1571 "BpfStorageReply",
1572 r#type.and_then(|t| BpfStorageReply::attr_from_type(t)),
1573 self.orig_loc,
1574 self.buf.as_ptr().wrapping_add(pos) as usize,
1575 )))
1576 }
1577}
1578impl<'a> std::fmt::Debug for IterableBpfStorageReply<'_> {
1579 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1580 let mut fmt = f.debug_struct("BpfStorageReply");
1581 for attr in self.clone() {
1582 let attr = match attr {
1583 Ok(a) => a,
1584 Err(err) => {
1585 fmt.finish()?;
1586 f.write_str("Err(")?;
1587 err.fmt(f)?;
1588 return f.write_str(")");
1589 }
1590 };
1591 match attr {
1592 BpfStorageReply::Storage(val) => fmt.field("Storage", &val),
1593 };
1594 }
1595 fmt.finish()
1596 }
1597}
1598impl IterableBpfStorageReply<'_> {
1599 pub fn lookup_attr(
1600 &self,
1601 offset: usize,
1602 missing_type: Option<u16>,
1603 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1604 let mut stack = Vec::new();
1605 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1606 if cur == offset {
1607 stack.push(("BpfStorageReply", offset));
1608 return (
1609 stack,
1610 missing_type.and_then(|t| BpfStorageReply::attr_from_type(t)),
1611 );
1612 }
1613 if cur > offset || cur + self.buf.len() < offset {
1614 return (stack, None);
1615 }
1616 let mut attrs = self.clone();
1617 let mut last_off = cur + attrs.pos;
1618 let mut missing = None;
1619 while let Some(attr) = attrs.next() {
1620 let Ok(attr) = attr else { break };
1621 match attr {
1622 BpfStorageReply::Storage(val) => {
1623 (stack, missing) = val.lookup_attr(offset, missing_type);
1624 if !stack.is_empty() {
1625 break;
1626 }
1627 }
1628 _ => {}
1629 };
1630 last_off = cur + attrs.pos;
1631 }
1632 if !stack.is_empty() {
1633 stack.push(("BpfStorageReply", cur));
1634 }
1635 (stack, missing)
1636 }
1637}
1638#[derive(Clone)]
1639pub enum BpfStorage<'a> {
1640 Pad(&'a [u8]),
1641 MapId(u32),
1642 MapValue(u64),
1643}
1644impl<'a> IterableBpfStorage<'a> {
1645 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
1646 let mut iter = self.clone();
1647 iter.pos = 0;
1648 for attr in iter {
1649 if let BpfStorage::Pad(val) = attr? {
1650 return Ok(val);
1651 }
1652 }
1653 Err(ErrorContext::new_missing(
1654 "BpfStorage",
1655 "Pad",
1656 self.orig_loc,
1657 self.buf.as_ptr() as usize,
1658 ))
1659 }
1660 pub fn get_map_id(&self) -> Result<u32, ErrorContext> {
1661 let mut iter = self.clone();
1662 iter.pos = 0;
1663 for attr in iter {
1664 if let BpfStorage::MapId(val) = attr? {
1665 return Ok(val);
1666 }
1667 }
1668 Err(ErrorContext::new_missing(
1669 "BpfStorage",
1670 "MapId",
1671 self.orig_loc,
1672 self.buf.as_ptr() as usize,
1673 ))
1674 }
1675 pub fn get_map_value(&self) -> Result<u64, ErrorContext> {
1676 let mut iter = self.clone();
1677 iter.pos = 0;
1678 for attr in iter {
1679 if let BpfStorage::MapValue(val) = attr? {
1680 return Ok(val);
1681 }
1682 }
1683 Err(ErrorContext::new_missing(
1684 "BpfStorage",
1685 "MapValue",
1686 self.orig_loc,
1687 self.buf.as_ptr() as usize,
1688 ))
1689 }
1690}
1691impl BpfStorage<'_> {
1692 pub fn new<'a>(buf: &'a [u8]) -> IterableBpfStorage<'a> {
1693 IterableBpfStorage::with_loc(buf, buf.as_ptr() as usize)
1694 }
1695 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1696 let res = match r#type {
1697 1u16 => "Pad",
1698 2u16 => "MapId",
1699 3u16 => "MapValue",
1700 _ => return None,
1701 };
1702 Some(res)
1703 }
1704}
1705#[derive(Clone, Copy, Default)]
1706pub struct IterableBpfStorage<'a> {
1707 buf: &'a [u8],
1708 pos: usize,
1709 orig_loc: usize,
1710}
1711impl<'a> IterableBpfStorage<'a> {
1712 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1713 Self {
1714 buf,
1715 pos: 0,
1716 orig_loc,
1717 }
1718 }
1719 pub fn get_buf(&self) -> &'a [u8] {
1720 self.buf
1721 }
1722}
1723impl<'a> Iterator for IterableBpfStorage<'a> {
1724 type Item = Result<BpfStorage<'a>, ErrorContext>;
1725 fn next(&mut self) -> Option<Self::Item> {
1726 let pos = self.pos;
1727 let mut r#type;
1728 loop {
1729 r#type = None;
1730 if self.buf.len() == self.pos {
1731 return None;
1732 }
1733 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1734 break;
1735 };
1736 r#type = Some(header.r#type);
1737 let res = match header.r#type {
1738 1u16 => BpfStorage::Pad({
1739 let res = Some(next);
1740 let Some(val) = res else { break };
1741 val
1742 }),
1743 2u16 => BpfStorage::MapId({
1744 let res = parse_u32(next);
1745 let Some(val) = res else { break };
1746 val
1747 }),
1748 3u16 => BpfStorage::MapValue({
1749 let res = parse_u64(next);
1750 let Some(val) = res else { break };
1751 val
1752 }),
1753 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1754 n => continue,
1755 };
1756 return Some(Ok(res));
1757 }
1758 Some(Err(ErrorContext::new(
1759 "BpfStorage",
1760 r#type.and_then(|t| BpfStorage::attr_from_type(t)),
1761 self.orig_loc,
1762 self.buf.as_ptr().wrapping_add(pos) as usize,
1763 )))
1764 }
1765}
1766impl<'a> std::fmt::Debug for IterableBpfStorage<'_> {
1767 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1768 let mut fmt = f.debug_struct("BpfStorage");
1769 for attr in self.clone() {
1770 let attr = match attr {
1771 Ok(a) => a,
1772 Err(err) => {
1773 fmt.finish()?;
1774 f.write_str("Err(")?;
1775 err.fmt(f)?;
1776 return f.write_str(")");
1777 }
1778 };
1779 match attr {
1780 BpfStorage::Pad(val) => fmt.field("Pad", &val),
1781 BpfStorage::MapId(val) => fmt.field("MapId", &val),
1782 BpfStorage::MapValue(val) => fmt.field("MapValue", &val),
1783 };
1784 }
1785 fmt.finish()
1786 }
1787}
1788impl IterableBpfStorage<'_> {
1789 pub fn lookup_attr(
1790 &self,
1791 offset: usize,
1792 missing_type: Option<u16>,
1793 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1794 let mut stack = Vec::new();
1795 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1796 if cur == offset {
1797 stack.push(("BpfStorage", offset));
1798 return (
1799 stack,
1800 missing_type.and_then(|t| BpfStorage::attr_from_type(t)),
1801 );
1802 }
1803 if cur > offset || cur + self.buf.len() < offset {
1804 return (stack, None);
1805 }
1806 let mut attrs = self.clone();
1807 let mut last_off = cur + attrs.pos;
1808 while let Some(attr) = attrs.next() {
1809 let Ok(attr) = attr else { break };
1810 match attr {
1811 BpfStorage::Pad(val) => {
1812 if last_off == offset {
1813 stack.push(("Pad", last_off));
1814 break;
1815 }
1816 }
1817 BpfStorage::MapId(val) => {
1818 if last_off == offset {
1819 stack.push(("MapId", last_off));
1820 break;
1821 }
1822 }
1823 BpfStorage::MapValue(val) => {
1824 if last_off == offset {
1825 stack.push(("MapValue", last_off));
1826 break;
1827 }
1828 }
1829 _ => {}
1830 };
1831 last_off = cur + attrs.pos;
1832 }
1833 if !stack.is_empty() {
1834 stack.push(("BpfStorage", cur));
1835 }
1836 (stack, None)
1837 }
1838}
1839pub struct PushUlpInfoAttrs<Prev: Rec> {
1840 pub(crate) prev: Option<Prev>,
1841 pub(crate) header_offset: Option<usize>,
1842}
1843impl<Prev: Rec> Rec for PushUlpInfoAttrs<Prev> {
1844 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1845 self.prev.as_mut().unwrap().as_rec_mut()
1846 }
1847 fn as_rec(&self) -> &Vec<u8> {
1848 self.prev.as_ref().unwrap().as_rec()
1849 }
1850}
1851impl<Prev: Rec> PushUlpInfoAttrs<Prev> {
1852 pub fn new(prev: Prev) -> Self {
1853 Self {
1854 prev: Some(prev),
1855 header_offset: None,
1856 }
1857 }
1858 pub fn end_nested(mut self) -> Prev {
1859 let mut prev = self.prev.take().unwrap();
1860 if let Some(header_offset) = &self.header_offset {
1861 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1862 }
1863 prev
1864 }
1865 #[doc = "ULP name (e.g., \"tls\", \"mptcp\")"]
1866 pub fn push_name(mut self, value: &CStr) -> Self {
1867 push_header(
1868 self.as_rec_mut(),
1869 1u16,
1870 value.to_bytes_with_nul().len() as u16,
1871 );
1872 self.as_rec_mut().extend(value.to_bytes_with_nul());
1873 self
1874 }
1875 #[doc = "ULP name (e.g., \"tls\", \"mptcp\")"]
1876 pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
1877 push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
1878 self.as_rec_mut().extend(value);
1879 self.as_rec_mut().push(0);
1880 self
1881 }
1882 #[doc = "TLS-specific information"]
1883 pub fn push_tls(mut self, value: &[u8]) -> Self {
1884 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
1885 self.as_rec_mut().extend(value);
1886 self
1887 }
1888 #[doc = "MPTCP-specific information"]
1889 pub fn push_mptcp(mut self, value: &[u8]) -> Self {
1890 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1891 self.as_rec_mut().extend(value);
1892 self
1893 }
1894}
1895impl<Prev: Rec> Drop for PushUlpInfoAttrs<Prev> {
1896 fn drop(&mut self) {
1897 if let Some(prev) = &mut self.prev {
1898 if let Some(header_offset) = &self.header_offset {
1899 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1900 }
1901 }
1902 }
1903}
1904pub struct PushRequestAttrs<Prev: Rec> {
1905 pub(crate) prev: Option<Prev>,
1906 pub(crate) header_offset: Option<usize>,
1907}
1908impl<Prev: Rec> Rec for PushRequestAttrs<Prev> {
1909 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1910 self.prev.as_mut().unwrap().as_rec_mut()
1911 }
1912 fn as_rec(&self) -> &Vec<u8> {
1913 self.prev.as_ref().unwrap().as_rec()
1914 }
1915}
1916impl<Prev: Rec> PushRequestAttrs<Prev> {
1917 pub fn new(prev: Prev) -> Self {
1918 Self {
1919 prev: Some(prev),
1920 header_offset: None,
1921 }
1922 }
1923 pub fn end_nested(mut self) -> Prev {
1924 let mut prev = self.prev.take().unwrap();
1925 if let Some(header_offset) = &self.header_offset {
1926 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1927 }
1928 prev
1929 }
1930 #[doc = "See bytecode-op"]
1931 pub fn push_bytecode(mut self, value: &[u8]) -> Self {
1932 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
1933 self.as_rec_mut().extend(value);
1934 self
1935 }
1936 pub fn nested_bpf_storages(mut self) -> PushBpfStorageReq<Self> {
1937 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
1938 PushBpfStorageReq {
1939 prev: Some(self),
1940 header_offset: Some(header_offset),
1941 }
1942 }
1943 pub fn push_protocol(mut self, value: u32) -> Self {
1944 push_header(self.as_rec_mut(), 3u16, 4 as u16);
1945 self.as_rec_mut().extend(value.to_ne_bytes());
1946 self
1947 }
1948}
1949impl<Prev: Rec> Drop for PushRequestAttrs<Prev> {
1950 fn drop(&mut self) {
1951 if let Some(prev) = &mut self.prev {
1952 if let Some(header_offset) = &self.header_offset {
1953 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1954 }
1955 }
1956 }
1957}
1958pub struct PushReplyAttrs<Prev: Rec> {
1959 pub(crate) prev: Option<Prev>,
1960 pub(crate) header_offset: Option<usize>,
1961}
1962impl<Prev: Rec> Rec for PushReplyAttrs<Prev> {
1963 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1964 self.prev.as_mut().unwrap().as_rec_mut()
1965 }
1966 fn as_rec(&self) -> &Vec<u8> {
1967 self.prev.as_ref().unwrap().as_rec()
1968 }
1969}
1970impl<Prev: Rec> PushReplyAttrs<Prev> {
1971 pub fn new(prev: Prev) -> Self {
1972 Self {
1973 prev: Some(prev),
1974 header_offset: None,
1975 }
1976 }
1977 pub fn end_nested(mut self) -> Prev {
1978 let mut prev = self.prev.take().unwrap();
1979 if let Some(header_offset) = &self.header_offset {
1980 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1981 }
1982 prev
1983 }
1984 #[doc = "Memory information extension"]
1985 pub fn push_meminfo(mut self, value: Meminfo) -> Self {
1986 push_header(self.as_rec_mut(), 1u16, value.as_slice().len() as u16);
1987 self.as_rec_mut().extend(value.as_slice());
1988 self
1989 }
1990 pub fn push_tcp_info(mut self, value: TcpInfo) -> Self {
1991 push_header(self.as_rec_mut(), 2u16, value.as_slice().len() as u16);
1992 self.as_rec_mut().extend(value.as_slice());
1993 self
1994 }
1995 #[doc = "TCP Vegas information"]
1996 pub fn push_vegasinfo(mut self, value: TcpvegasInfo) -> Self {
1997 push_header(self.as_rec_mut(), 3u16, value.as_slice().len() as u16);
1998 self.as_rec_mut().extend(value.as_slice());
1999 self
2000 }
2001 #[doc = "Congestion control algorithm name"]
2002 pub fn push_cong(mut self, value: &CStr) -> Self {
2003 push_header(
2004 self.as_rec_mut(),
2005 4u16,
2006 value.to_bytes_with_nul().len() as u16,
2007 );
2008 self.as_rec_mut().extend(value.to_bytes_with_nul());
2009 self
2010 }
2011 #[doc = "Congestion control algorithm name"]
2012 pub fn push_cong_bytes(mut self, value: &[u8]) -> Self {
2013 push_header(self.as_rec_mut(), 4u16, (value.len() + 1) as u16);
2014 self.as_rec_mut().extend(value);
2015 self.as_rec_mut().push(0);
2016 self
2017 }
2018 #[doc = "Type of Service"]
2019 pub fn push_tos(mut self, value: u8) -> Self {
2020 push_header(self.as_rec_mut(), 5u16, 1 as u16);
2021 self.as_rec_mut().extend(value.to_ne_bytes());
2022 self
2023 }
2024 #[doc = "Traffic Class"]
2025 pub fn push_tclass(mut self, value: u8) -> Self {
2026 push_header(self.as_rec_mut(), 6u16, 1 as u16);
2027 self.as_rec_mut().extend(value.to_ne_bytes());
2028 self
2029 }
2030 #[doc = "Socket memory information"]
2031 pub fn push_skmeminfo(mut self, value: &[u8]) -> Self {
2032 push_header(self.as_rec_mut(), 7u16, value.len() as u16);
2033 self.as_rec_mut().extend(value);
2034 self
2035 }
2036 #[doc = "Shutdown state"]
2037 pub fn push_shutdown(mut self, value: u8) -> Self {
2038 push_header(self.as_rec_mut(), 8u16, 1 as u16);
2039 self.as_rec_mut().extend(value.to_ne_bytes());
2040 self
2041 }
2042 #[doc = "TCP DCTCP information (request as INET_DIAG_VEGASINFO)"]
2043 pub fn push_dctcpinfo(mut self, value: TcpDctcpInfo) -> Self {
2044 push_header(self.as_rec_mut(), 9u16, value.as_slice().len() as u16);
2045 self.as_rec_mut().extend(value.as_slice());
2046 self
2047 }
2048 #[doc = "Raw socket protocol (response attribute only)"]
2049 pub fn push_protocol(mut self, value: u8) -> Self {
2050 push_header(self.as_rec_mut(), 10u16, 1 as u16);
2051 self.as_rec_mut().extend(value.to_ne_bytes());
2052 self
2053 }
2054 #[doc = "IPv6-only socket flag"]
2055 pub fn push_skv6only(mut self, value: ()) -> Self {
2056 push_header(self.as_rec_mut(), 11u16, 0 as u16);
2057 self
2058 }
2059 #[doc = "Local addresses. SCTP thing."]
2060 pub fn push_locals(mut self, value: &[u8]) -> Self {
2061 push_header(self.as_rec_mut(), 12u16, value.len() as u16);
2062 self.as_rec_mut().extend(value);
2063 self
2064 }
2065 #[doc = "Peer addresses. SCTP thing."]
2066 pub fn push_peers(mut self, value: &[u8]) -> Self {
2067 push_header(self.as_rec_mut(), 13u16, value.len() as u16);
2068 self.as_rec_mut().extend(value);
2069 self
2070 }
2071 pub fn push_pad(mut self, value: &[u8]) -> Self {
2072 push_header(self.as_rec_mut(), 14u16, value.len() as u16);
2073 self.as_rec_mut().extend(value);
2074 self
2075 }
2076 #[doc = "Socket mark (only with CAP_NET_ADMIN)"]
2077 pub fn push_mark(mut self, value: u32) -> Self {
2078 push_header(self.as_rec_mut(), 15u16, 4 as u16);
2079 self.as_rec_mut().extend(value.to_ne_bytes());
2080 self
2081 }
2082 #[doc = "TCP BBR information (request as INET_DIAG_VEGASINFO)"]
2083 pub fn push_bbritfo(mut self, value: TcpBbrInfo) -> Self {
2084 push_header(self.as_rec_mut(), 16u16, value.as_slice().len() as u16);
2085 self.as_rec_mut().extend(value.as_slice());
2086 self
2087 }
2088 #[doc = "Class ID (request as INET_DIAG_TCLASS)"]
2089 pub fn push_class_id(mut self, value: u32) -> Self {
2090 push_header(self.as_rec_mut(), 17u16, 4 as u16);
2091 self.as_rec_mut().extend(value.to_ne_bytes());
2092 self
2093 }
2094 #[doc = "MD5 signature information"]
2095 pub fn push_md5sig(mut self, value: &[u8]) -> Self {
2096 push_header(self.as_rec_mut(), 18u16, value.len() as u16);
2097 self.as_rec_mut().extend(value);
2098 self
2099 }
2100 #[doc = "Upper Layer Protocol information"]
2101 pub fn nested_ulp_info(mut self) -> PushUlpInfoAttrs<Self> {
2102 let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
2103 PushUlpInfoAttrs {
2104 prev: Some(self),
2105 header_offset: Some(header_offset),
2106 }
2107 }
2108 #[doc = "BPF storage information\nAttribute may repeat multiple times (treat it as array)"]
2109 pub fn nested_sk_bpf_storages(mut self) -> PushBpfStorageReply<Self> {
2110 let header_offset = push_nested_header(self.as_rec_mut(), 20u16);
2111 PushBpfStorageReply {
2112 prev: Some(self),
2113 header_offset: Some(header_offset),
2114 }
2115 }
2116 #[doc = "Cgroup ID"]
2117 pub fn push_cgroup_id(mut self, value: u64) -> Self {
2118 push_header(self.as_rec_mut(), 21u16, 8 as u16);
2119 self.as_rec_mut().extend(value.to_ne_bytes());
2120 self
2121 }
2122 #[doc = "Socket options\nAssociated type: \"SockoptFlag\" (enum)"]
2123 pub fn push_sockopt_flags(mut self, value: u16) -> Self {
2124 push_header(self.as_rec_mut(), 22u16, 2 as u16);
2125 self.as_rec_mut().extend(value.to_ne_bytes());
2126 self
2127 }
2128}
2129impl<Prev: Rec> Drop for PushReplyAttrs<Prev> {
2130 fn drop(&mut self) {
2131 if let Some(prev) = &mut self.prev {
2132 if let Some(header_offset) = &self.header_offset {
2133 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2134 }
2135 }
2136 }
2137}
2138pub struct PushBpfStorageReq<Prev: Rec> {
2139 pub(crate) prev: Option<Prev>,
2140 pub(crate) header_offset: Option<usize>,
2141}
2142impl<Prev: Rec> Rec for PushBpfStorageReq<Prev> {
2143 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2144 self.prev.as_mut().unwrap().as_rec_mut()
2145 }
2146 fn as_rec(&self) -> &Vec<u8> {
2147 self.prev.as_ref().unwrap().as_rec()
2148 }
2149}
2150impl<Prev: Rec> PushBpfStorageReq<Prev> {
2151 pub fn new(prev: Prev) -> Self {
2152 Self {
2153 prev: Some(prev),
2154 header_offset: None,
2155 }
2156 }
2157 pub fn end_nested(mut self) -> Prev {
2158 let mut prev = self.prev.take().unwrap();
2159 if let Some(header_offset) = &self.header_offset {
2160 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2161 }
2162 prev
2163 }
2164 #[doc = "Attribute may repeat multiple times (treat it as array)"]
2165 pub fn push_map_fd(mut self, value: u32) -> Self {
2166 push_header(self.as_rec_mut(), 1u16, 4 as u16);
2167 self.as_rec_mut().extend(value.to_ne_bytes());
2168 self
2169 }
2170}
2171impl<Prev: Rec> Drop for PushBpfStorageReq<Prev> {
2172 fn drop(&mut self) {
2173 if let Some(prev) = &mut self.prev {
2174 if let Some(header_offset) = &self.header_offset {
2175 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2176 }
2177 }
2178 }
2179}
2180pub struct PushBpfStorageReply<Prev: Rec> {
2181 pub(crate) prev: Option<Prev>,
2182 pub(crate) header_offset: Option<usize>,
2183}
2184impl<Prev: Rec> Rec for PushBpfStorageReply<Prev> {
2185 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2186 self.prev.as_mut().unwrap().as_rec_mut()
2187 }
2188 fn as_rec(&self) -> &Vec<u8> {
2189 self.prev.as_ref().unwrap().as_rec()
2190 }
2191}
2192impl<Prev: Rec> PushBpfStorageReply<Prev> {
2193 pub fn new(prev: Prev) -> Self {
2194 Self {
2195 prev: Some(prev),
2196 header_offset: None,
2197 }
2198 }
2199 pub fn end_nested(mut self) -> Prev {
2200 let mut prev = self.prev.take().unwrap();
2201 if let Some(header_offset) = &self.header_offset {
2202 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2203 }
2204 prev
2205 }
2206 pub fn nested_storage(mut self) -> PushBpfStorage<Self> {
2207 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
2208 PushBpfStorage {
2209 prev: Some(self),
2210 header_offset: Some(header_offset),
2211 }
2212 }
2213}
2214impl<Prev: Rec> Drop for PushBpfStorageReply<Prev> {
2215 fn drop(&mut self) {
2216 if let Some(prev) = &mut self.prev {
2217 if let Some(header_offset) = &self.header_offset {
2218 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2219 }
2220 }
2221 }
2222}
2223pub struct PushBpfStorage<Prev: Rec> {
2224 pub(crate) prev: Option<Prev>,
2225 pub(crate) header_offset: Option<usize>,
2226}
2227impl<Prev: Rec> Rec for PushBpfStorage<Prev> {
2228 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2229 self.prev.as_mut().unwrap().as_rec_mut()
2230 }
2231 fn as_rec(&self) -> &Vec<u8> {
2232 self.prev.as_ref().unwrap().as_rec()
2233 }
2234}
2235impl<Prev: Rec> PushBpfStorage<Prev> {
2236 pub fn new(prev: Prev) -> Self {
2237 Self {
2238 prev: Some(prev),
2239 header_offset: None,
2240 }
2241 }
2242 pub fn end_nested(mut self) -> Prev {
2243 let mut prev = self.prev.take().unwrap();
2244 if let Some(header_offset) = &self.header_offset {
2245 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2246 }
2247 prev
2248 }
2249 pub fn push_pad(mut self, value: &[u8]) -> Self {
2250 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
2251 self.as_rec_mut().extend(value);
2252 self
2253 }
2254 pub fn push_map_id(mut self, value: u32) -> Self {
2255 push_header(self.as_rec_mut(), 2u16, 4 as u16);
2256 self.as_rec_mut().extend(value.to_ne_bytes());
2257 self
2258 }
2259 pub fn push_map_value(mut self, value: u64) -> Self {
2260 push_header(self.as_rec_mut(), 3u16, 8 as u16);
2261 self.as_rec_mut().extend(value.to_ne_bytes());
2262 self
2263 }
2264}
2265impl<Prev: Rec> Drop for PushBpfStorage<Prev> {
2266 fn drop(&mut self) {
2267 if let Some(prev) = &mut self.prev {
2268 if let Some(header_offset) = &self.header_offset {
2269 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2270 }
2271 }
2272 }
2273}
2274#[repr(C, packed(4))]
2275pub struct Sockid {
2276 pub _sport_be: u16,
2277 pub _dport_be: u16,
2278 pub src: [u8; 16usize],
2279 pub dst: [u8; 16usize],
2280 pub r#if: u32,
2281 pub cookie: [u8; 8usize],
2282}
2283impl Clone for Sockid {
2284 fn clone(&self) -> Self {
2285 Self::new_from_array(*self.as_array())
2286 }
2287}
2288#[doc = "Create zero-initialized struct"]
2289impl Default for Sockid {
2290 fn default() -> Self {
2291 Self::new()
2292 }
2293}
2294impl Sockid {
2295 #[doc = "Create zero-initialized struct"]
2296 pub fn new() -> Self {
2297 Self::new_from_array([0u8; Self::len()])
2298 }
2299 #[doc = "Copy from contents from slice"]
2300 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2301 if other.len() != Self::len() {
2302 return None;
2303 }
2304 let mut buf = [0u8; Self::len()];
2305 buf.clone_from_slice(other);
2306 Some(Self::new_from_array(buf))
2307 }
2308 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2309 pub fn new_from_zeroed(other: &[u8]) -> Self {
2310 let mut buf = [0u8; Self::len()];
2311 let len = buf.len().min(other.len());
2312 buf[..len].clone_from_slice(&other[..len]);
2313 Self::new_from_array(buf)
2314 }
2315 pub fn new_from_array(buf: [u8; 48usize]) -> Self {
2316 unsafe { std::mem::transmute(buf) }
2317 }
2318 pub fn as_slice(&self) -> &[u8] {
2319 unsafe {
2320 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2321 std::slice::from_raw_parts(ptr, Self::len())
2322 }
2323 }
2324 pub fn from_slice(buf: &[u8]) -> &Self {
2325 assert!(buf.len() >= Self::len());
2326 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2327 unsafe { std::mem::transmute(buf.as_ptr()) }
2328 }
2329 pub fn as_array(&self) -> &[u8; 48usize] {
2330 unsafe { std::mem::transmute(self) }
2331 }
2332 pub fn from_array(buf: &[u8; 48usize]) -> &Self {
2333 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2334 unsafe { std::mem::transmute(buf) }
2335 }
2336 pub fn into_array(self) -> [u8; 48usize] {
2337 unsafe { std::mem::transmute(self) }
2338 }
2339 pub const fn len() -> usize {
2340 const _: () = assert!(std::mem::size_of::<Sockid>() == 48usize);
2341 48usize
2342 }
2343 pub fn sport(&self) -> u16 {
2344 u16::from_be(self._sport_be)
2345 }
2346 pub fn set_sport(&mut self, value: u16) {
2347 self._sport_be = value.to_be();
2348 }
2349 pub fn dport(&self) -> u16 {
2350 u16::from_be(self._dport_be)
2351 }
2352 pub fn set_dport(&mut self, value: u16) {
2353 self._dport_be = value.to_be();
2354 }
2355}
2356impl std::fmt::Debug for Sockid {
2357 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2358 fmt.debug_struct("Sockid")
2359 .field("sport", &self.sport())
2360 .field("dport", &self.dport())
2361 .field("src", &FormatHex(self.src))
2362 .field("dst", &FormatHex(self.dst))
2363 .field("if", &self.r#if)
2364 .field("cookie", &FormatHex(self.cookie))
2365 .finish()
2366 }
2367}
2368#[repr(C, packed(4))]
2369pub struct Req {
2370 #[doc = "Family of addresses"]
2371 pub family: u8,
2372 pub src_len: u8,
2373 pub dst_len: u8,
2374 #[doc = "Query extended information"]
2375 pub ext: u8,
2376 pub sockid: Sockid,
2377 #[doc = "States to dump\nAssociated type: \"TcpState\" (1 bit per enumeration)"]
2378 pub states: u32,
2379 #[doc = "Tables to dump (NI)"]
2380 pub dbs: u32,
2381}
2382impl Clone for Req {
2383 fn clone(&self) -> Self {
2384 Self::new_from_array(*self.as_array())
2385 }
2386}
2387#[doc = "Create zero-initialized struct"]
2388impl Default for Req {
2389 fn default() -> Self {
2390 Self::new()
2391 }
2392}
2393impl Req {
2394 #[doc = "Create zero-initialized struct"]
2395 pub fn new() -> Self {
2396 Self::new_from_array([0u8; Self::len()])
2397 }
2398 #[doc = "Copy from contents from slice"]
2399 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2400 if other.len() != Self::len() {
2401 return None;
2402 }
2403 let mut buf = [0u8; Self::len()];
2404 buf.clone_from_slice(other);
2405 Some(Self::new_from_array(buf))
2406 }
2407 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2408 pub fn new_from_zeroed(other: &[u8]) -> Self {
2409 let mut buf = [0u8; Self::len()];
2410 let len = buf.len().min(other.len());
2411 buf[..len].clone_from_slice(&other[..len]);
2412 Self::new_from_array(buf)
2413 }
2414 pub fn new_from_array(buf: [u8; 60usize]) -> Self {
2415 unsafe { std::mem::transmute(buf) }
2416 }
2417 pub fn as_slice(&self) -> &[u8] {
2418 unsafe {
2419 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2420 std::slice::from_raw_parts(ptr, Self::len())
2421 }
2422 }
2423 pub fn from_slice(buf: &[u8]) -> &Self {
2424 assert!(buf.len() >= Self::len());
2425 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2426 unsafe { std::mem::transmute(buf.as_ptr()) }
2427 }
2428 pub fn as_array(&self) -> &[u8; 60usize] {
2429 unsafe { std::mem::transmute(self) }
2430 }
2431 pub fn from_array(buf: &[u8; 60usize]) -> &Self {
2432 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2433 unsafe { std::mem::transmute(buf) }
2434 }
2435 pub fn into_array(self) -> [u8; 60usize] {
2436 unsafe { std::mem::transmute(self) }
2437 }
2438 pub const fn len() -> usize {
2439 const _: () = assert!(std::mem::size_of::<Req>() == 60usize);
2440 60usize
2441 }
2442}
2443impl std::fmt::Debug for Req {
2444 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2445 fmt.debug_struct("Req")
2446 .field("family", &self.family)
2447 .field("src_len", &self.src_len)
2448 .field("dst_len", &self.dst_len)
2449 .field("ext", &self.ext)
2450 .field("sockid", &self.sockid)
2451 .field(
2452 "states",
2453 &FormatFlags(self.states.into(), |val| {
2454 TcpState::from_value(val.trailing_zeros().into())
2455 }),
2456 )
2457 .field("dbs", &self.dbs)
2458 .finish()
2459 }
2460}
2461#[repr(C, packed(4))]
2462pub struct ReqV2 {
2463 pub family: u8,
2464 pub protocol: u8,
2465 pub ext: u8,
2466 pub pad: u8,
2467 #[doc = "Associated type: \"TcpState\" (1 bit per enumeration)"]
2468 pub states: u32,
2469 pub sockid: Sockid,
2470}
2471impl Clone for ReqV2 {
2472 fn clone(&self) -> Self {
2473 Self::new_from_array(*self.as_array())
2474 }
2475}
2476#[doc = "Create zero-initialized struct"]
2477impl Default for ReqV2 {
2478 fn default() -> Self {
2479 Self::new()
2480 }
2481}
2482impl ReqV2 {
2483 #[doc = "Create zero-initialized struct"]
2484 pub fn new() -> Self {
2485 Self::new_from_array([0u8; Self::len()])
2486 }
2487 #[doc = "Copy from contents from slice"]
2488 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2489 if other.len() != Self::len() {
2490 return None;
2491 }
2492 let mut buf = [0u8; Self::len()];
2493 buf.clone_from_slice(other);
2494 Some(Self::new_from_array(buf))
2495 }
2496 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2497 pub fn new_from_zeroed(other: &[u8]) -> Self {
2498 let mut buf = [0u8; Self::len()];
2499 let len = buf.len().min(other.len());
2500 buf[..len].clone_from_slice(&other[..len]);
2501 Self::new_from_array(buf)
2502 }
2503 pub fn new_from_array(buf: [u8; 56usize]) -> Self {
2504 unsafe { std::mem::transmute(buf) }
2505 }
2506 pub fn as_slice(&self) -> &[u8] {
2507 unsafe {
2508 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2509 std::slice::from_raw_parts(ptr, Self::len())
2510 }
2511 }
2512 pub fn from_slice(buf: &[u8]) -> &Self {
2513 assert!(buf.len() >= Self::len());
2514 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2515 unsafe { std::mem::transmute(buf.as_ptr()) }
2516 }
2517 pub fn as_array(&self) -> &[u8; 56usize] {
2518 unsafe { std::mem::transmute(self) }
2519 }
2520 pub fn from_array(buf: &[u8; 56usize]) -> &Self {
2521 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2522 unsafe { std::mem::transmute(buf) }
2523 }
2524 pub fn into_array(self) -> [u8; 56usize] {
2525 unsafe { std::mem::transmute(self) }
2526 }
2527 pub const fn len() -> usize {
2528 const _: () = assert!(std::mem::size_of::<ReqV2>() == 56usize);
2529 56usize
2530 }
2531}
2532impl std::fmt::Debug for ReqV2 {
2533 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2534 fmt.debug_struct("ReqV2")
2535 .field("family", &self.family)
2536 .field("protocol", &self.protocol)
2537 .field("ext", &self.ext)
2538 .field("pad", &self.pad)
2539 .field(
2540 "states",
2541 &FormatFlags(self.states.into(), |val| {
2542 TcpState::from_value(val.trailing_zeros().into())
2543 }),
2544 )
2545 .field("sockid", &self.sockid)
2546 .finish()
2547 }
2548}
2549#[repr(C, packed(4))]
2550pub struct ReqRaw {
2551 pub family: u8,
2552 pub protocol: u8,
2553 pub ext: u8,
2554 pub raw_protocol: u8,
2555 #[doc = "Associated type: \"TcpState\" (1 bit per enumeration)"]
2556 pub states: u32,
2557 pub sockid: Sockid,
2558}
2559impl Clone for ReqRaw {
2560 fn clone(&self) -> Self {
2561 Self::new_from_array(*self.as_array())
2562 }
2563}
2564#[doc = "Create zero-initialized struct"]
2565impl Default for ReqRaw {
2566 fn default() -> Self {
2567 Self::new()
2568 }
2569}
2570impl ReqRaw {
2571 #[doc = "Create zero-initialized struct"]
2572 pub fn new() -> Self {
2573 Self::new_from_array([0u8; Self::len()])
2574 }
2575 #[doc = "Copy from contents from slice"]
2576 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2577 if other.len() != Self::len() {
2578 return None;
2579 }
2580 let mut buf = [0u8; Self::len()];
2581 buf.clone_from_slice(other);
2582 Some(Self::new_from_array(buf))
2583 }
2584 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2585 pub fn new_from_zeroed(other: &[u8]) -> Self {
2586 let mut buf = [0u8; Self::len()];
2587 let len = buf.len().min(other.len());
2588 buf[..len].clone_from_slice(&other[..len]);
2589 Self::new_from_array(buf)
2590 }
2591 pub fn new_from_array(buf: [u8; 56usize]) -> Self {
2592 unsafe { std::mem::transmute(buf) }
2593 }
2594 pub fn as_slice(&self) -> &[u8] {
2595 unsafe {
2596 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2597 std::slice::from_raw_parts(ptr, Self::len())
2598 }
2599 }
2600 pub fn from_slice(buf: &[u8]) -> &Self {
2601 assert!(buf.len() >= Self::len());
2602 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2603 unsafe { std::mem::transmute(buf.as_ptr()) }
2604 }
2605 pub fn as_array(&self) -> &[u8; 56usize] {
2606 unsafe { std::mem::transmute(self) }
2607 }
2608 pub fn from_array(buf: &[u8; 56usize]) -> &Self {
2609 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2610 unsafe { std::mem::transmute(buf) }
2611 }
2612 pub fn into_array(self) -> [u8; 56usize] {
2613 unsafe { std::mem::transmute(self) }
2614 }
2615 pub const fn len() -> usize {
2616 const _: () = assert!(std::mem::size_of::<ReqRaw>() == 56usize);
2617 56usize
2618 }
2619}
2620impl std::fmt::Debug for ReqRaw {
2621 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2622 fmt.debug_struct("ReqRaw")
2623 .field("family", &self.family)
2624 .field("protocol", &self.protocol)
2625 .field("ext", &self.ext)
2626 .field("raw_protocol", &self.raw_protocol)
2627 .field(
2628 "states",
2629 &FormatFlags(self.states.into(), |val| {
2630 TcpState::from_value(val.trailing_zeros().into())
2631 }),
2632 )
2633 .field("sockid", &self.sockid)
2634 .finish()
2635 }
2636}
2637#[repr(C, packed(4))]
2638pub struct Msg {
2639 pub family: u8,
2640 #[doc = "Associated type: \"TcpState\" (enum)"]
2641 pub state: u8,
2642 pub timer: u8,
2643 pub retrans: u8,
2644 pub sockid: Sockid,
2645 pub expires: u32,
2646 pub rqueue: u32,
2647 pub wqueue: u32,
2648 pub uid: u32,
2649 pub inode: u32,
2650}
2651impl Clone for Msg {
2652 fn clone(&self) -> Self {
2653 Self::new_from_array(*self.as_array())
2654 }
2655}
2656#[doc = "Create zero-initialized struct"]
2657impl Default for Msg {
2658 fn default() -> Self {
2659 Self::new()
2660 }
2661}
2662impl Msg {
2663 #[doc = "Create zero-initialized struct"]
2664 pub fn new() -> Self {
2665 Self::new_from_array([0u8; Self::len()])
2666 }
2667 #[doc = "Copy from contents from slice"]
2668 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2669 if other.len() != Self::len() {
2670 return None;
2671 }
2672 let mut buf = [0u8; Self::len()];
2673 buf.clone_from_slice(other);
2674 Some(Self::new_from_array(buf))
2675 }
2676 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2677 pub fn new_from_zeroed(other: &[u8]) -> Self {
2678 let mut buf = [0u8; Self::len()];
2679 let len = buf.len().min(other.len());
2680 buf[..len].clone_from_slice(&other[..len]);
2681 Self::new_from_array(buf)
2682 }
2683 pub fn new_from_array(buf: [u8; 72usize]) -> Self {
2684 unsafe { std::mem::transmute(buf) }
2685 }
2686 pub fn as_slice(&self) -> &[u8] {
2687 unsafe {
2688 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2689 std::slice::from_raw_parts(ptr, Self::len())
2690 }
2691 }
2692 pub fn from_slice(buf: &[u8]) -> &Self {
2693 assert!(buf.len() >= Self::len());
2694 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2695 unsafe { std::mem::transmute(buf.as_ptr()) }
2696 }
2697 pub fn as_array(&self) -> &[u8; 72usize] {
2698 unsafe { std::mem::transmute(self) }
2699 }
2700 pub fn from_array(buf: &[u8; 72usize]) -> &Self {
2701 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2702 unsafe { std::mem::transmute(buf) }
2703 }
2704 pub fn into_array(self) -> [u8; 72usize] {
2705 unsafe { std::mem::transmute(self) }
2706 }
2707 pub const fn len() -> usize {
2708 const _: () = assert!(std::mem::size_of::<Msg>() == 72usize);
2709 72usize
2710 }
2711}
2712impl std::fmt::Debug for Msg {
2713 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2714 fmt.debug_struct("Msg")
2715 .field("family", &self.family)
2716 .field(
2717 "state",
2718 &FormatEnum(self.state.into(), TcpState::from_value),
2719 )
2720 .field("timer", &self.timer)
2721 .field("retrans", &self.retrans)
2722 .field("sockid", &self.sockid)
2723 .field("expires", &self.expires)
2724 .field("rqueue", &self.rqueue)
2725 .field("wqueue", &self.wqueue)
2726 .field("uid", &self.uid)
2727 .field("inode", &self.inode)
2728 .finish()
2729 }
2730}
2731#[repr(C, packed(4))]
2732pub struct BytecodeOp {
2733 #[doc = "Associated type: \"BytecodeOpCode\" (enum)"]
2734 pub code: u8,
2735 #[doc = "offset to jump on match"]
2736 pub yes: u8,
2737 #[doc = "offset to jump on non-match"]
2738 pub no: u16,
2739}
2740impl Clone for BytecodeOp {
2741 fn clone(&self) -> Self {
2742 Self::new_from_array(*self.as_array())
2743 }
2744}
2745#[doc = "Create zero-initialized struct"]
2746impl Default for BytecodeOp {
2747 fn default() -> Self {
2748 Self::new()
2749 }
2750}
2751impl BytecodeOp {
2752 #[doc = "Create zero-initialized struct"]
2753 pub fn new() -> Self {
2754 Self::new_from_array([0u8; Self::len()])
2755 }
2756 #[doc = "Copy from contents from slice"]
2757 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2758 if other.len() != Self::len() {
2759 return None;
2760 }
2761 let mut buf = [0u8; Self::len()];
2762 buf.clone_from_slice(other);
2763 Some(Self::new_from_array(buf))
2764 }
2765 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2766 pub fn new_from_zeroed(other: &[u8]) -> Self {
2767 let mut buf = [0u8; Self::len()];
2768 let len = buf.len().min(other.len());
2769 buf[..len].clone_from_slice(&other[..len]);
2770 Self::new_from_array(buf)
2771 }
2772 pub fn new_from_array(buf: [u8; 4usize]) -> Self {
2773 unsafe { std::mem::transmute(buf) }
2774 }
2775 pub fn as_slice(&self) -> &[u8] {
2776 unsafe {
2777 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2778 std::slice::from_raw_parts(ptr, Self::len())
2779 }
2780 }
2781 pub fn from_slice(buf: &[u8]) -> &Self {
2782 assert!(buf.len() >= Self::len());
2783 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2784 unsafe { std::mem::transmute(buf.as_ptr()) }
2785 }
2786 pub fn as_array(&self) -> &[u8; 4usize] {
2787 unsafe { std::mem::transmute(self) }
2788 }
2789 pub fn from_array(buf: &[u8; 4usize]) -> &Self {
2790 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2791 unsafe { std::mem::transmute(buf) }
2792 }
2793 pub fn into_array(self) -> [u8; 4usize] {
2794 unsafe { std::mem::transmute(self) }
2795 }
2796 pub const fn len() -> usize {
2797 const _: () = assert!(std::mem::size_of::<BytecodeOp>() == 4usize);
2798 4usize
2799 }
2800}
2801impl std::fmt::Debug for BytecodeOp {
2802 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2803 fmt.debug_struct("BytecodeOp")
2804 .field(
2805 "code",
2806 &FormatEnum(self.code.into(), BytecodeOpCode::from_value),
2807 )
2808 .field("yes", &self.yes)
2809 .field("no", &self.no)
2810 .finish()
2811 }
2812}
2813#[derive(Debug)]
2814#[repr(C, packed(4))]
2815pub struct Hostcond {
2816 #[doc = "Socket address family"]
2817 pub family: u8,
2818 #[doc = "Number of bits to compare"]
2819 pub prefix_len: u8,
2820 pub _pad_2: [u8; 2usize],
2821 pub port: i32,
2822}
2823impl Clone for Hostcond {
2824 fn clone(&self) -> Self {
2825 Self::new_from_array(*self.as_array())
2826 }
2827}
2828#[doc = "Create zero-initialized struct"]
2829impl Default for Hostcond {
2830 fn default() -> Self {
2831 Self::new()
2832 }
2833}
2834impl Hostcond {
2835 #[doc = "Create zero-initialized struct"]
2836 pub fn new() -> Self {
2837 Self::new_from_array([0u8; Self::len()])
2838 }
2839 #[doc = "Copy from contents from slice"]
2840 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2841 if other.len() != Self::len() {
2842 return None;
2843 }
2844 let mut buf = [0u8; Self::len()];
2845 buf.clone_from_slice(other);
2846 Some(Self::new_from_array(buf))
2847 }
2848 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2849 pub fn new_from_zeroed(other: &[u8]) -> Self {
2850 let mut buf = [0u8; Self::len()];
2851 let len = buf.len().min(other.len());
2852 buf[..len].clone_from_slice(&other[..len]);
2853 Self::new_from_array(buf)
2854 }
2855 pub fn new_from_array(buf: [u8; 8usize]) -> Self {
2856 unsafe { std::mem::transmute(buf) }
2857 }
2858 pub fn as_slice(&self) -> &[u8] {
2859 unsafe {
2860 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2861 std::slice::from_raw_parts(ptr, Self::len())
2862 }
2863 }
2864 pub fn from_slice(buf: &[u8]) -> &Self {
2865 assert!(buf.len() >= Self::len());
2866 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2867 unsafe { std::mem::transmute(buf.as_ptr()) }
2868 }
2869 pub fn as_array(&self) -> &[u8; 8usize] {
2870 unsafe { std::mem::transmute(self) }
2871 }
2872 pub fn from_array(buf: &[u8; 8usize]) -> &Self {
2873 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2874 unsafe { std::mem::transmute(buf) }
2875 }
2876 pub fn into_array(self) -> [u8; 8usize] {
2877 unsafe { std::mem::transmute(self) }
2878 }
2879 pub const fn len() -> usize {
2880 const _: () = assert!(std::mem::size_of::<Hostcond>() == 8usize);
2881 8usize
2882 }
2883}
2884#[derive(Debug)]
2885#[repr(C, packed(4))]
2886pub struct Markcond {
2887 pub mark: u32,
2888 pub mask: u32,
2889}
2890impl Clone for Markcond {
2891 fn clone(&self) -> Self {
2892 Self::new_from_array(*self.as_array())
2893 }
2894}
2895#[doc = "Create zero-initialized struct"]
2896impl Default for Markcond {
2897 fn default() -> Self {
2898 Self::new()
2899 }
2900}
2901impl Markcond {
2902 #[doc = "Create zero-initialized struct"]
2903 pub fn new() -> Self {
2904 Self::new_from_array([0u8; Self::len()])
2905 }
2906 #[doc = "Copy from contents from slice"]
2907 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2908 if other.len() != Self::len() {
2909 return None;
2910 }
2911 let mut buf = [0u8; Self::len()];
2912 buf.clone_from_slice(other);
2913 Some(Self::new_from_array(buf))
2914 }
2915 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2916 pub fn new_from_zeroed(other: &[u8]) -> Self {
2917 let mut buf = [0u8; Self::len()];
2918 let len = buf.len().min(other.len());
2919 buf[..len].clone_from_slice(&other[..len]);
2920 Self::new_from_array(buf)
2921 }
2922 pub fn new_from_array(buf: [u8; 8usize]) -> Self {
2923 unsafe { std::mem::transmute(buf) }
2924 }
2925 pub fn as_slice(&self) -> &[u8] {
2926 unsafe {
2927 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2928 std::slice::from_raw_parts(ptr, Self::len())
2929 }
2930 }
2931 pub fn from_slice(buf: &[u8]) -> &Self {
2932 assert!(buf.len() >= Self::len());
2933 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2934 unsafe { std::mem::transmute(buf.as_ptr()) }
2935 }
2936 pub fn as_array(&self) -> &[u8; 8usize] {
2937 unsafe { std::mem::transmute(self) }
2938 }
2939 pub fn from_array(buf: &[u8; 8usize]) -> &Self {
2940 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
2941 unsafe { std::mem::transmute(buf) }
2942 }
2943 pub fn into_array(self) -> [u8; 8usize] {
2944 unsafe { std::mem::transmute(self) }
2945 }
2946 pub const fn len() -> usize {
2947 const _: () = assert!(std::mem::size_of::<Markcond>() == 8usize);
2948 8usize
2949 }
2950}
2951#[derive(Debug)]
2952#[repr(C, packed(4))]
2953pub struct Meminfo {
2954 pub rmem: u32,
2955 pub wmem: u32,
2956 pub fmem: u32,
2957 pub tmem: u32,
2958}
2959impl Clone for Meminfo {
2960 fn clone(&self) -> Self {
2961 Self::new_from_array(*self.as_array())
2962 }
2963}
2964#[doc = "Create zero-initialized struct"]
2965impl Default for Meminfo {
2966 fn default() -> Self {
2967 Self::new()
2968 }
2969}
2970impl Meminfo {
2971 #[doc = "Create zero-initialized struct"]
2972 pub fn new() -> Self {
2973 Self::new_from_array([0u8; Self::len()])
2974 }
2975 #[doc = "Copy from contents from slice"]
2976 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
2977 if other.len() != Self::len() {
2978 return None;
2979 }
2980 let mut buf = [0u8; Self::len()];
2981 buf.clone_from_slice(other);
2982 Some(Self::new_from_array(buf))
2983 }
2984 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
2985 pub fn new_from_zeroed(other: &[u8]) -> Self {
2986 let mut buf = [0u8; Self::len()];
2987 let len = buf.len().min(other.len());
2988 buf[..len].clone_from_slice(&other[..len]);
2989 Self::new_from_array(buf)
2990 }
2991 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
2992 unsafe { std::mem::transmute(buf) }
2993 }
2994 pub fn as_slice(&self) -> &[u8] {
2995 unsafe {
2996 let ptr: *const u8 = std::mem::transmute(self as *const Self);
2997 std::slice::from_raw_parts(ptr, Self::len())
2998 }
2999 }
3000 pub fn from_slice(buf: &[u8]) -> &Self {
3001 assert!(buf.len() >= Self::len());
3002 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3003 unsafe { std::mem::transmute(buf.as_ptr()) }
3004 }
3005 pub fn as_array(&self) -> &[u8; 16usize] {
3006 unsafe { std::mem::transmute(self) }
3007 }
3008 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
3009 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3010 unsafe { std::mem::transmute(buf) }
3011 }
3012 pub fn into_array(self) -> [u8; 16usize] {
3013 unsafe { std::mem::transmute(self) }
3014 }
3015 pub const fn len() -> usize {
3016 const _: () = assert!(std::mem::size_of::<Meminfo>() == 16usize);
3017 16usize
3018 }
3019}
3020#[derive(Debug)]
3021#[repr(C, packed(4))]
3022pub struct TcpvegasInfo {
3023 pub enabled: u32,
3024 pub rttcnt: u32,
3025 pub rtt: u32,
3026 pub minrtt: u32,
3027}
3028impl Clone for TcpvegasInfo {
3029 fn clone(&self) -> Self {
3030 Self::new_from_array(*self.as_array())
3031 }
3032}
3033#[doc = "Create zero-initialized struct"]
3034impl Default for TcpvegasInfo {
3035 fn default() -> Self {
3036 Self::new()
3037 }
3038}
3039impl TcpvegasInfo {
3040 #[doc = "Create zero-initialized struct"]
3041 pub fn new() -> Self {
3042 Self::new_from_array([0u8; Self::len()])
3043 }
3044 #[doc = "Copy from contents from slice"]
3045 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
3046 if other.len() != Self::len() {
3047 return None;
3048 }
3049 let mut buf = [0u8; Self::len()];
3050 buf.clone_from_slice(other);
3051 Some(Self::new_from_array(buf))
3052 }
3053 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
3054 pub fn new_from_zeroed(other: &[u8]) -> Self {
3055 let mut buf = [0u8; Self::len()];
3056 let len = buf.len().min(other.len());
3057 buf[..len].clone_from_slice(&other[..len]);
3058 Self::new_from_array(buf)
3059 }
3060 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
3061 unsafe { std::mem::transmute(buf) }
3062 }
3063 pub fn as_slice(&self) -> &[u8] {
3064 unsafe {
3065 let ptr: *const u8 = std::mem::transmute(self as *const Self);
3066 std::slice::from_raw_parts(ptr, Self::len())
3067 }
3068 }
3069 pub fn from_slice(buf: &[u8]) -> &Self {
3070 assert!(buf.len() >= Self::len());
3071 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3072 unsafe { std::mem::transmute(buf.as_ptr()) }
3073 }
3074 pub fn as_array(&self) -> &[u8; 16usize] {
3075 unsafe { std::mem::transmute(self) }
3076 }
3077 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
3078 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3079 unsafe { std::mem::transmute(buf) }
3080 }
3081 pub fn into_array(self) -> [u8; 16usize] {
3082 unsafe { std::mem::transmute(self) }
3083 }
3084 pub const fn len() -> usize {
3085 const _: () = assert!(std::mem::size_of::<TcpvegasInfo>() == 16usize);
3086 16usize
3087 }
3088}
3089#[derive(Debug)]
3090#[repr(C, packed(4))]
3091pub struct TcpDctcpInfo {
3092 pub enabled: u16,
3093 pub ce_state: u16,
3094 pub alpha: u32,
3095 pub ab_ecn: u32,
3096 pub ab_tot: u32,
3097}
3098impl Clone for TcpDctcpInfo {
3099 fn clone(&self) -> Self {
3100 Self::new_from_array(*self.as_array())
3101 }
3102}
3103#[doc = "Create zero-initialized struct"]
3104impl Default for TcpDctcpInfo {
3105 fn default() -> Self {
3106 Self::new()
3107 }
3108}
3109impl TcpDctcpInfo {
3110 #[doc = "Create zero-initialized struct"]
3111 pub fn new() -> Self {
3112 Self::new_from_array([0u8; Self::len()])
3113 }
3114 #[doc = "Copy from contents from slice"]
3115 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
3116 if other.len() != Self::len() {
3117 return None;
3118 }
3119 let mut buf = [0u8; Self::len()];
3120 buf.clone_from_slice(other);
3121 Some(Self::new_from_array(buf))
3122 }
3123 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
3124 pub fn new_from_zeroed(other: &[u8]) -> Self {
3125 let mut buf = [0u8; Self::len()];
3126 let len = buf.len().min(other.len());
3127 buf[..len].clone_from_slice(&other[..len]);
3128 Self::new_from_array(buf)
3129 }
3130 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
3131 unsafe { std::mem::transmute(buf) }
3132 }
3133 pub fn as_slice(&self) -> &[u8] {
3134 unsafe {
3135 let ptr: *const u8 = std::mem::transmute(self as *const Self);
3136 std::slice::from_raw_parts(ptr, Self::len())
3137 }
3138 }
3139 pub fn from_slice(buf: &[u8]) -> &Self {
3140 assert!(buf.len() >= Self::len());
3141 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3142 unsafe { std::mem::transmute(buf.as_ptr()) }
3143 }
3144 pub fn as_array(&self) -> &[u8; 16usize] {
3145 unsafe { std::mem::transmute(self) }
3146 }
3147 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
3148 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3149 unsafe { std::mem::transmute(buf) }
3150 }
3151 pub fn into_array(self) -> [u8; 16usize] {
3152 unsafe { std::mem::transmute(self) }
3153 }
3154 pub const fn len() -> usize {
3155 const _: () = assert!(std::mem::size_of::<TcpDctcpInfo>() == 16usize);
3156 16usize
3157 }
3158}
3159#[derive(Debug)]
3160#[repr(C, packed(4))]
3161pub struct TcpBbrInfo {
3162 #[doc = "lower 32 bits of bw"]
3163 pub bw_lo: u32,
3164 #[doc = "upper 32 bits of bw"]
3165 pub bw_hi: u32,
3166 #[doc = "min-filtered RTT in uSec"]
3167 pub min_rtt: u32,
3168 #[doc = "pacing gain shifted left 8 bits"]
3169 pub pacing_gain: u32,
3170 #[doc = "cwnd gain shifted left 8 bits"]
3171 pub cwnd_gain: u32,
3172}
3173impl Clone for TcpBbrInfo {
3174 fn clone(&self) -> Self {
3175 Self::new_from_array(*self.as_array())
3176 }
3177}
3178#[doc = "Create zero-initialized struct"]
3179impl Default for TcpBbrInfo {
3180 fn default() -> Self {
3181 Self::new()
3182 }
3183}
3184impl TcpBbrInfo {
3185 #[doc = "Create zero-initialized struct"]
3186 pub fn new() -> Self {
3187 Self::new_from_array([0u8; Self::len()])
3188 }
3189 #[doc = "Copy from contents from slice"]
3190 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
3191 if other.len() != Self::len() {
3192 return None;
3193 }
3194 let mut buf = [0u8; Self::len()];
3195 buf.clone_from_slice(other);
3196 Some(Self::new_from_array(buf))
3197 }
3198 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
3199 pub fn new_from_zeroed(other: &[u8]) -> Self {
3200 let mut buf = [0u8; Self::len()];
3201 let len = buf.len().min(other.len());
3202 buf[..len].clone_from_slice(&other[..len]);
3203 Self::new_from_array(buf)
3204 }
3205 pub fn new_from_array(buf: [u8; 20usize]) -> Self {
3206 unsafe { std::mem::transmute(buf) }
3207 }
3208 pub fn as_slice(&self) -> &[u8] {
3209 unsafe {
3210 let ptr: *const u8 = std::mem::transmute(self as *const Self);
3211 std::slice::from_raw_parts(ptr, Self::len())
3212 }
3213 }
3214 pub fn from_slice(buf: &[u8]) -> &Self {
3215 assert!(buf.len() >= Self::len());
3216 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3217 unsafe { std::mem::transmute(buf.as_ptr()) }
3218 }
3219 pub fn as_array(&self) -> &[u8; 20usize] {
3220 unsafe { std::mem::transmute(self) }
3221 }
3222 pub fn from_array(buf: &[u8; 20usize]) -> &Self {
3223 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3224 unsafe { std::mem::transmute(buf) }
3225 }
3226 pub fn into_array(self) -> [u8; 20usize] {
3227 unsafe { std::mem::transmute(self) }
3228 }
3229 pub const fn len() -> usize {
3230 const _: () = assert!(std::mem::size_of::<TcpBbrInfo>() == 20usize);
3231 20usize
3232 }
3233}
3234#[repr(C, packed(4))]
3235pub struct TcpInfo {
3236 #[doc = "TCP state\nAssociated type: \"TcpState\" (enum)"]
3237 pub state: u8,
3238 #[doc = "Congestion avoidance state"]
3239 pub ca_state: u8,
3240 #[doc = "Number of retransmits"]
3241 pub retransmits: u8,
3242 #[doc = "Number of probes"]
3243 pub probes: u8,
3244 #[doc = "Backoff count"]
3245 pub backoff: u8,
3246 #[doc = "TCP options"]
3247 pub options: u8,
3248 pub _bits_snd_wscale: u8,
3249 pub _bits_delivery_rate_app_limited: u8,
3250 #[doc = "Retransmission timeout in microseconds"]
3251 pub rto: u32,
3252 #[doc = "Delayed ACK timeout in microseconds"]
3253 pub ato: u32,
3254 #[doc = "Send maximum segment size"]
3255 pub snd_mss: u32,
3256 #[doc = "Receive maximum segment size"]
3257 pub rcv_mss: u32,
3258 #[doc = "Number of unacknowledged segments"]
3259 pub unacked: u32,
3260 #[doc = "Number of SACKed segments"]
3261 pub sacked: u32,
3262 #[doc = "Number of lost segments"]
3263 pub lost: u32,
3264 #[doc = "Number of retransmitted segments"]
3265 pub retrans: u32,
3266 #[doc = "Forward Acknowledgment count"]
3267 pub fackets: u32,
3268 #[doc = "Time since last data sent (jiffies)"]
3269 pub last_data_sent: u32,
3270 #[doc = "Time since last ACK sent (jiffies, Not remembered, sorry.)"]
3271 pub last_ack_sent: u32,
3272 #[doc = "Time since last data received (jiffies)"]
3273 pub last_data_recv: u32,
3274 #[doc = "Time since last ACK received (jiffies)"]
3275 pub last_ack_recv: u32,
3276 #[doc = "Path MTU"]
3277 pub pmtu: u32,
3278 #[doc = "Receive slow start threshold"]
3279 pub rcv_ssthresh: u32,
3280 #[doc = "Smoothed round trip time in microseconds"]
3281 pub rtt: u32,
3282 #[doc = "Round trip time variation"]
3283 pub rttvar: u32,
3284 #[doc = "Send slow start threshold"]
3285 pub snd_ssthresh: u32,
3286 #[doc = "Send congestion window"]
3287 pub snd_cwnd: u32,
3288 #[doc = "Advertised MSS"]
3289 pub advmss: u32,
3290 #[doc = "Reordering threshold"]
3291 pub reordering: u32,
3292 #[doc = "Receiver side RTT"]
3293 pub rcv_rtt: u32,
3294 #[doc = "Receiver space"]
3295 pub rcv_space: u32,
3296 #[doc = "Total number of retransmitted segments"]
3297 pub total_retrans: u32,
3298 #[doc = "Pacing rate in bytes per second"]
3299 pub pacing_rate: u64,
3300 #[doc = "Maximum pacing rate in bytes per second"]
3301 pub max_pacing_rate: u64,
3302 #[doc = "RFC4898 tcpEStatsAppHCThruOctetsAcked"]
3303 pub bytes_acked: u64,
3304 #[doc = "RFC4898 tcpEStatsAppHCThruOctetsReceived"]
3305 pub bytes_received: u64,
3306 #[doc = "RFC4898 tcpEStatsPerfSegsOut"]
3307 pub segs_out: u32,
3308 #[doc = "RFC4898 tcpEStatsPerfSegsIn"]
3309 pub segs_in: u32,
3310 #[doc = "Bytes in write queue not yet sent"]
3311 pub notsent_bytes: u32,
3312 #[doc = "Minimum RTT observed in microseconds"]
3313 pub min_rtt: u32,
3314 #[doc = "RFC4898 tcpEStatsDataSegsIn"]
3315 pub data_segs_in: u32,
3316 #[doc = "RFC4898 tcpEStatsDataSegsOut"]
3317 pub data_segs_out: u32,
3318 #[doc = "Delivery rate in bytes per second"]
3319 pub delivery_rate: u64,
3320 #[doc = "Time (usec) busy sending data"]
3321 pub busy_time: u64,
3322 #[doc = "Time (usec) limited by receive window"]
3323 pub rwnd_limited: u64,
3324 #[doc = "Time (usec) limited by send buffer"]
3325 pub sndbuf_limited: u64,
3326 #[doc = "Packets delivered"]
3327 pub delivered: u32,
3328 #[doc = "Packets delivered with CE marks"]
3329 pub delivered_ce: u32,
3330 #[doc = "RFC4898 tcpEStatsPerfHCDataOctetsOut"]
3331 pub bytes_sent: u64,
3332 #[doc = "RFC4898 tcpEStatsPerfOctetsRetrans"]
3333 pub bytes_retrans: u64,
3334 #[doc = "RFC4898 tcpEStatsStackDSACKDups"]
3335 pub dsack_dups: u32,
3336 #[doc = "Reordering events seen"]
3337 pub reord_seen: u32,
3338 #[doc = "Out-of-order packets received"]
3339 pub rcv_ooopack: u32,
3340 #[doc = "Peer's advertised receive window after scaling (bytes)"]
3341 pub snd_wnd: u32,
3342 #[doc = "Local advertised receive window after scaling (bytes)"]
3343 pub rcv_wnd: u32,
3344 #[doc = "PLB or timeout triggered rehash attempts"]
3345 pub rehash: u32,
3346 #[doc = "Total number of RTO timeouts, including SYN/SYN-ACK and recurring timeouts"]
3347 pub total_rto: u16,
3348 #[doc = "Total number of RTO recoveries, including any unfinished recovery"]
3349 pub total_rto_recoveries: u16,
3350 #[doc = "Total time spent in RTO recoveries in milliseconds, including any unfinished recovery"]
3351 pub total_rto_time: u32,
3352 #[doc = "Number of CE marks received"]
3353 pub received_ce: u32,
3354 #[doc = "Accurate ECN byte counters for ECT(1)"]
3355 pub delivered_e1_bytes: u32,
3356 #[doc = "Accurate ECN byte counters for ECT(0)"]
3357 pub delivered_e0_bytes: u32,
3358 #[doc = "Accurate ECN byte counters for CE"]
3359 pub delivered_ce_bytes: u32,
3360 #[doc = "Received bytes with ECT(1) marks"]
3361 pub received_e1_bytes: u32,
3362 #[doc = "Received bytes with ECT(0) marks"]
3363 pub received_e0_bytes: u32,
3364 #[doc = "Received bytes with CE marks"]
3365 pub received_ce_bytes: u32,
3366 #[doc = "ACK ECN failure mode"]
3367 pub accecn_fail_mode: u16,
3368 #[doc = "ACK ECN option seen"]
3369 pub accecn_opt_seen: u16,
3370}
3371impl Clone for TcpInfo {
3372 fn clone(&self) -> Self {
3373 Self::new_from_array(*self.as_array())
3374 }
3375}
3376#[doc = "Create zero-initialized struct"]
3377impl Default for TcpInfo {
3378 fn default() -> Self {
3379 Self::new()
3380 }
3381}
3382impl TcpInfo {
3383 #[doc = "Create zero-initialized struct"]
3384 pub fn new() -> Self {
3385 Self::new_from_array([0u8; Self::len()])
3386 }
3387 #[doc = "Copy from contents from slice"]
3388 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
3389 if other.len() != Self::len() {
3390 return None;
3391 }
3392 let mut buf = [0u8; Self::len()];
3393 buf.clone_from_slice(other);
3394 Some(Self::new_from_array(buf))
3395 }
3396 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
3397 pub fn new_from_zeroed(other: &[u8]) -> Self {
3398 let mut buf = [0u8; Self::len()];
3399 let len = buf.len().min(other.len());
3400 buf[..len].clone_from_slice(&other[..len]);
3401 Self::new_from_array(buf)
3402 }
3403 pub fn new_from_array(buf: [u8; 280usize]) -> Self {
3404 unsafe { std::mem::transmute(buf) }
3405 }
3406 pub fn as_slice(&self) -> &[u8] {
3407 unsafe {
3408 let ptr: *const u8 = std::mem::transmute(self as *const Self);
3409 std::slice::from_raw_parts(ptr, Self::len())
3410 }
3411 }
3412 pub fn from_slice(buf: &[u8]) -> &Self {
3413 assert!(buf.len() >= Self::len());
3414 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3415 unsafe { std::mem::transmute(buf.as_ptr()) }
3416 }
3417 pub fn as_array(&self) -> &[u8; 280usize] {
3418 unsafe { std::mem::transmute(self) }
3419 }
3420 pub fn from_array(buf: &[u8; 280usize]) -> &Self {
3421 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
3422 unsafe { std::mem::transmute(buf) }
3423 }
3424 pub fn into_array(self) -> [u8; 280usize] {
3425 unsafe { std::mem::transmute(self) }
3426 }
3427 pub const fn len() -> usize {
3428 const _: () = assert!(std::mem::size_of::<TcpInfo>() == 280usize);
3429 280usize
3430 }
3431 #[doc = "Send window scale"]
3432 pub fn snd_wscale(&self) -> u8 {
3433 (((self._bits_snd_wscale as u32) << 28u32) >> 28u32) as u8
3434 }
3435 #[doc = "Send window scale"]
3436 pub fn set_snd_wscale(&mut self, value: u8) {
3437 let mask = (1 << 4usize) - 1;
3438 self._bits_snd_wscale =
3439 (self._bits_snd_wscale & (!(mask << 0usize))) | ((value & mask) << 0usize);
3440 }
3441 #[doc = "Receive window scale"]
3442 pub fn rcv_wscale(&self) -> u8 {
3443 (((self._bits_snd_wscale as u32) << 24u32) >> 28u32) as u8
3444 }
3445 #[doc = "Receive window scale"]
3446 pub fn set_rcv_wscale(&mut self, value: u8) {
3447 let mask = (1 << 4usize) - 1;
3448 self._bits_snd_wscale =
3449 (self._bits_snd_wscale & (!(mask << 4usize))) | ((value & mask) << 4usize);
3450 }
3451 #[doc = "Delivery rate application limited flag"]
3452 pub fn delivery_rate_app_limited(&self) -> u8 {
3453 (((self._bits_delivery_rate_app_limited as u32) << 31u32) >> 31u32) as u8
3454 }
3455 #[doc = "Delivery rate application limited flag"]
3456 pub fn set_delivery_rate_app_limited(&mut self, value: u8) {
3457 let mask = (1 << 1usize) - 1;
3458 self._bits_delivery_rate_app_limited = (self._bits_delivery_rate_app_limited
3459 & (!(mask << 0usize)))
3460 | ((value & mask) << 0usize);
3461 }
3462 #[doc = "FastOpen client failure code"]
3463 pub fn fastopen_client_fail(&self) -> u8 {
3464 (((self._bits_delivery_rate_app_limited as u32) << 29u32) >> 30u32) as u8
3465 }
3466 #[doc = "FastOpen client failure code"]
3467 pub fn set_fastopen_client_fail(&mut self, value: u8) {
3468 let mask = (1 << 2usize) - 1;
3469 self._bits_delivery_rate_app_limited = (self._bits_delivery_rate_app_limited
3470 & (!(mask << 1usize)))
3471 | ((value & mask) << 1usize);
3472 }
3473}
3474impl std::fmt::Debug for TcpInfo {
3475 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3476 fmt.debug_struct("TcpInfo")
3477 .field(
3478 "state",
3479 &FormatEnum(self.state.into(), TcpState::from_value),
3480 )
3481 .field("ca_state", &self.ca_state)
3482 .field("retransmits", &self.retransmits)
3483 .field("probes", &self.probes)
3484 .field("backoff", &self.backoff)
3485 .field("options", &self.options)
3486 .field("snd_wscale", &self.snd_wscale())
3487 .field("rcv_wscale", &self.rcv_wscale())
3488 .field(
3489 "delivery_rate_app_limited",
3490 &self.delivery_rate_app_limited(),
3491 )
3492 .field("fastopen_client_fail", &self.fastopen_client_fail())
3493 .field("rto", &self.rto)
3494 .field("ato", &self.ato)
3495 .field("snd_mss", &self.snd_mss)
3496 .field("rcv_mss", &self.rcv_mss)
3497 .field("unacked", &self.unacked)
3498 .field("sacked", &self.sacked)
3499 .field("lost", &self.lost)
3500 .field("retrans", &self.retrans)
3501 .field("fackets", &self.fackets)
3502 .field("last_data_sent", &self.last_data_sent)
3503 .field("last_ack_sent", &self.last_ack_sent)
3504 .field("last_data_recv", &self.last_data_recv)
3505 .field("last_ack_recv", &self.last_ack_recv)
3506 .field("pmtu", &self.pmtu)
3507 .field("rcv_ssthresh", &self.rcv_ssthresh)
3508 .field("rtt", &self.rtt)
3509 .field("rttvar", &self.rttvar)
3510 .field("snd_ssthresh", &self.snd_ssthresh)
3511 .field("snd_cwnd", &self.snd_cwnd)
3512 .field("advmss", &self.advmss)
3513 .field("reordering", &self.reordering)
3514 .field("rcv_rtt", &self.rcv_rtt)
3515 .field("rcv_space", &self.rcv_space)
3516 .field("total_retrans", &self.total_retrans)
3517 .field("pacing_rate", &{ self.pacing_rate })
3518 .field("max_pacing_rate", &{ self.max_pacing_rate })
3519 .field("bytes_acked", &{ self.bytes_acked })
3520 .field("bytes_received", &{ self.bytes_received })
3521 .field("segs_out", &self.segs_out)
3522 .field("segs_in", &self.segs_in)
3523 .field("notsent_bytes", &self.notsent_bytes)
3524 .field("min_rtt", &self.min_rtt)
3525 .field("data_segs_in", &self.data_segs_in)
3526 .field("data_segs_out", &self.data_segs_out)
3527 .field("delivery_rate", &{ self.delivery_rate })
3528 .field("busy_time", &{ self.busy_time })
3529 .field("rwnd_limited", &{ self.rwnd_limited })
3530 .field("sndbuf_limited", &{ self.sndbuf_limited })
3531 .field("delivered", &self.delivered)
3532 .field("delivered_ce", &self.delivered_ce)
3533 .field("bytes_sent", &{ self.bytes_sent })
3534 .field("bytes_retrans", &{ self.bytes_retrans })
3535 .field("dsack_dups", &self.dsack_dups)
3536 .field("reord_seen", &self.reord_seen)
3537 .field("rcv_ooopack", &self.rcv_ooopack)
3538 .field("snd_wnd", &self.snd_wnd)
3539 .field("rcv_wnd", &self.rcv_wnd)
3540 .field("rehash", &self.rehash)
3541 .field("total_rto", &self.total_rto)
3542 .field("total_rto_recoveries", &self.total_rto_recoveries)
3543 .field("total_rto_time", &self.total_rto_time)
3544 .field("received_ce", &self.received_ce)
3545 .field("delivered_e1_bytes", &self.delivered_e1_bytes)
3546 .field("delivered_e0_bytes", &self.delivered_e0_bytes)
3547 .field("delivered_ce_bytes", &self.delivered_ce_bytes)
3548 .field("received_e1_bytes", &self.received_e1_bytes)
3549 .field("received_e0_bytes", &self.received_e0_bytes)
3550 .field("received_ce_bytes", &self.received_ce_bytes)
3551 .field("accecn_fail_mode", &self.accecn_fail_mode)
3552 .field("accecn_opt_seen", &self.accecn_opt_seen)
3553 .finish()
3554 }
3555}
3556#[derive(Debug)]
3557pub struct RequestOpTcpDiagDumpRequest<'r> {
3558 request: Request<'r>,
3559}
3560impl<'r> RequestOpTcpDiagDumpRequest<'r> {
3561 pub fn new(mut request: Request<'r>, header: &ReqV2) -> Self {
3562 Self::write_header(&mut request.buf_mut(), header);
3563 Self {
3564 request: request.set_dump(),
3565 }
3566 }
3567 pub fn encode(&mut self) -> PushRequestAttrs<&mut Vec<u8>> {
3568 PushRequestAttrs::new(self.request.buf_mut())
3569 }
3570 pub fn into_encoder(self) -> PushRequestAttrs<RequestBuf<'r>> {
3571 PushRequestAttrs::new(self.request.buf)
3572 }
3573 fn write_header<Prev: Rec>(prev: &mut Prev, header: &ReqV2) {
3574 prev.as_rec_mut().extend(header.as_slice());
3575 }
3576 pub fn decode_request<'a>(buf: &'a [u8]) -> (ReqV2, IterableRequestAttrs<'a>) {
3577 let (header, attrs) = buf.split_at(buf.len().min(ReqV2::len()));
3578 (
3579 ReqV2::new_from_slice(header).unwrap_or_default(),
3580 IterableRequestAttrs::with_loc(attrs, buf.as_ptr() as usize),
3581 )
3582 }
3583 fn decode_reply<'a>(buf: &'a [u8]) -> (Msg, IterableReplyAttrs<'a>) {
3584 let (header, attrs) = buf.split_at(buf.len().min(Msg::len()));
3585 (
3586 Msg::new_from_slice(header).unwrap_or_default(),
3587 IterableReplyAttrs::with_loc(attrs, buf.as_ptr() as usize),
3588 )
3589 }
3590}
3591impl NetlinkRequest for RequestOpTcpDiagDumpRequest<'_> {
3592 fn protocol(&self) -> Protocol {
3593 Protocol::Raw {
3594 protonum: 4u16,
3595 request_type: 20u16,
3596 }
3597 }
3598 fn flags(&self) -> u16 {
3599 self.request.flags
3600 }
3601 fn payload(&self) -> &[u8] {
3602 self.request.buf()
3603 }
3604 type ReplyType<'buf> = (Msg, IterableReplyAttrs<'buf>);
3605 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3606 Self::decode_reply(buf)
3607 }
3608 fn lookup(
3609 buf: &[u8],
3610 offset: usize,
3611 missing_type: Option<u16>,
3612 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3613 Self::decode_request(buf)
3614 .1
3615 .lookup_attr(offset, missing_type)
3616 }
3617}
3618#[derive(Debug)]
3619pub struct RequestOpUdpDiagDumpRequest<'r> {
3620 request: Request<'r>,
3621}
3622impl<'r> RequestOpUdpDiagDumpRequest<'r> {
3623 pub fn new(mut request: Request<'r>, header: &ReqV2) -> Self {
3624 Self::write_header(&mut request.buf_mut(), header);
3625 Self {
3626 request: request.set_dump(),
3627 }
3628 }
3629 pub fn encode(&mut self) -> PushRequestAttrs<&mut Vec<u8>> {
3630 PushRequestAttrs::new(self.request.buf_mut())
3631 }
3632 pub fn into_encoder(self) -> PushRequestAttrs<RequestBuf<'r>> {
3633 PushRequestAttrs::new(self.request.buf)
3634 }
3635 fn write_header<Prev: Rec>(prev: &mut Prev, header: &ReqV2) {
3636 prev.as_rec_mut().extend(header.as_slice());
3637 }
3638 pub fn decode_request<'a>(buf: &'a [u8]) -> (ReqV2, IterableRequestAttrs<'a>) {
3639 let (header, attrs) = buf.split_at(buf.len().min(ReqV2::len()));
3640 (
3641 ReqV2::new_from_slice(header).unwrap_or_default(),
3642 IterableRequestAttrs::with_loc(attrs, buf.as_ptr() as usize),
3643 )
3644 }
3645 fn decode_reply<'a>(buf: &'a [u8]) -> (Msg, IterableReplyAttrs<'a>) {
3646 let (header, attrs) = buf.split_at(buf.len().min(Msg::len()));
3647 (
3648 Msg::new_from_slice(header).unwrap_or_default(),
3649 IterableReplyAttrs::with_loc(attrs, buf.as_ptr() as usize),
3650 )
3651 }
3652}
3653impl NetlinkRequest for RequestOpUdpDiagDumpRequest<'_> {
3654 fn protocol(&self) -> Protocol {
3655 Protocol::Raw {
3656 protonum: 4u16,
3657 request_type: 20u16,
3658 }
3659 }
3660 fn flags(&self) -> u16 {
3661 self.request.flags
3662 }
3663 fn payload(&self) -> &[u8] {
3664 self.request.buf()
3665 }
3666 type ReplyType<'buf> = (Msg, IterableReplyAttrs<'buf>);
3667 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3668 Self::decode_reply(buf)
3669 }
3670 fn lookup(
3671 buf: &[u8],
3672 offset: usize,
3673 missing_type: Option<u16>,
3674 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3675 Self::decode_request(buf)
3676 .1
3677 .lookup_attr(offset, missing_type)
3678 }
3679}
3680#[derive(Debug)]
3681pub struct ChainedFinal<'a> {
3682 inner: Chained<'a>,
3683}
3684#[derive(Debug)]
3685pub struct Chained<'a> {
3686 buf: RequestBuf<'a>,
3687 first_seq: u32,
3688 lookups: Vec<(&'static str, LookupFn)>,
3689 last_header_offset: usize,
3690 last_kind: Option<RequestInfo>,
3691}
3692impl<'a> ChainedFinal<'a> {
3693 pub fn into_chained(self) -> Chained<'a> {
3694 self.inner
3695 }
3696 pub fn buf(&self) -> &Vec<u8> {
3697 self.inner.buf()
3698 }
3699 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3700 self.inner.buf_mut()
3701 }
3702 fn get_index(&self, seq: u32) -> Option<u32> {
3703 let min = self.inner.first_seq;
3704 let max = min.wrapping_add(self.inner.lookups.len() as u32);
3705 return if min <= max {
3706 (min..max).contains(&seq).then(|| seq - min)
3707 } else if min <= seq {
3708 Some(seq - min)
3709 } else if seq < max {
3710 Some(u32::MAX - min + seq)
3711 } else {
3712 None
3713 };
3714 }
3715}
3716impl crate::traits::NetlinkChained for ChainedFinal<'_> {
3717 fn protonum(&self) -> u16 {
3718 PROTONUM
3719 }
3720 fn payload(&self) -> &[u8] {
3721 self.buf()
3722 }
3723 fn chain_len(&self) -> usize {
3724 self.inner.lookups.len()
3725 }
3726 fn get_index(&self, seq: u32) -> Option<usize> {
3727 self.get_index(seq).map(|n| n as usize)
3728 }
3729 fn name(&self, index: usize) -> &'static str {
3730 self.inner.lookups[index].0
3731 }
3732 fn lookup(&self, index: usize) -> LookupFn {
3733 self.inner.lookups[index].1
3734 }
3735}
3736impl Chained<'static> {
3737 pub fn new(first_seq: u32) -> Self {
3738 Self::new_from_buf(Vec::new(), first_seq)
3739 }
3740 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
3741 Self {
3742 buf: RequestBuf::Own(buf),
3743 first_seq,
3744 lookups: Vec::new(),
3745 last_header_offset: 0,
3746 last_kind: None,
3747 }
3748 }
3749 pub fn into_buf(self) -> Vec<u8> {
3750 match self.buf {
3751 RequestBuf::Own(buf) => buf,
3752 _ => unreachable!(),
3753 }
3754 }
3755}
3756impl<'a> Chained<'a> {
3757 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
3758 Self {
3759 buf: RequestBuf::Ref(buf),
3760 first_seq,
3761 lookups: Vec::new(),
3762 last_header_offset: 0,
3763 last_kind: None,
3764 }
3765 }
3766 pub fn finalize(mut self) -> ChainedFinal<'a> {
3767 self.update_header();
3768 ChainedFinal { inner: self }
3769 }
3770 pub fn request(&mut self) -> Request<'_> {
3771 self.update_header();
3772 self.last_header_offset = self.buf().len();
3773 self.buf_mut()
3774 .extend_from_slice(PushNlmsghdr::new().as_slice());
3775 let mut request = Request::new_extend(self.buf.buf_mut());
3776 self.last_kind = None;
3777 request.writeback = Some(&mut self.last_kind);
3778 request
3779 }
3780 pub fn buf(&self) -> &Vec<u8> {
3781 self.buf.buf()
3782 }
3783 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3784 self.buf.buf_mut()
3785 }
3786 fn update_header(&mut self) {
3787 let Some(RequestInfo {
3788 protocol,
3789 flags,
3790 name,
3791 lookup,
3792 }) = self.last_kind
3793 else {
3794 if !self.buf().is_empty() {
3795 assert_eq!(
3796 self.last_header_offset + PushNlmsghdr::len(),
3797 self.buf().len()
3798 );
3799 self.buf.buf_mut().truncate(self.last_header_offset);
3800 }
3801 return;
3802 };
3803 let header_offset = self.last_header_offset;
3804 let request_type = match protocol {
3805 Protocol::Raw { request_type, .. } => request_type,
3806 Protocol::Generic(_) => unreachable!(),
3807 };
3808 let index = self.lookups.len();
3809 let seq = self.first_seq.wrapping_add(index as u32);
3810 self.lookups.push((name, lookup));
3811 let buf = self.buf_mut();
3812 align(buf);
3813 let mut header = PushNlmsghdr::new();
3814 header.set_len((buf.len() - header_offset) as u32);
3815 header.set_type(request_type);
3816 header.set_flags(flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16);
3817 header.set_seq(seq);
3818 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
3819 }
3820}
3821use crate::traits::LookupFn;
3822use crate::utils::RequestBuf;
3823#[derive(Debug)]
3824pub struct Request<'buf> {
3825 buf: RequestBuf<'buf>,
3826 flags: u16,
3827 writeback: Option<&'buf mut Option<RequestInfo>>,
3828}
3829#[allow(unused)]
3830#[derive(Debug, Clone)]
3831pub struct RequestInfo {
3832 protocol: Protocol,
3833 flags: u16,
3834 name: &'static str,
3835 lookup: LookupFn,
3836}
3837impl Request<'static> {
3838 pub fn new() -> Self {
3839 Self::new_from_buf(Vec::new())
3840 }
3841 pub fn new_from_buf(buf: Vec<u8>) -> Self {
3842 Self {
3843 flags: 0,
3844 buf: RequestBuf::Own(buf),
3845 writeback: None,
3846 }
3847 }
3848 pub fn into_buf(self) -> Vec<u8> {
3849 match self.buf {
3850 RequestBuf::Own(buf) => buf,
3851 _ => unreachable!(),
3852 }
3853 }
3854}
3855impl<'buf> Request<'buf> {
3856 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3857 buf.clear();
3858 Self::new_extend(buf)
3859 }
3860 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3861 Self {
3862 flags: 0,
3863 buf: RequestBuf::Ref(buf),
3864 writeback: None,
3865 }
3866 }
3867 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3868 let Some(writeback) = &mut self.writeback else {
3869 return;
3870 };
3871 **writeback = Some(RequestInfo {
3872 protocol,
3873 flags: self.flags,
3874 name,
3875 lookup,
3876 })
3877 }
3878 pub fn buf(&self) -> &Vec<u8> {
3879 self.buf.buf()
3880 }
3881 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3882 self.buf.buf_mut()
3883 }
3884 #[doc = "Set `NLM_F_CREATE` flag"]
3885 pub fn set_create(mut self) -> Self {
3886 self.flags |= consts::NLM_F_CREATE as u16;
3887 self
3888 }
3889 #[doc = "Set `NLM_F_EXCL` flag"]
3890 pub fn set_excl(mut self) -> Self {
3891 self.flags |= consts::NLM_F_EXCL as u16;
3892 self
3893 }
3894 #[doc = "Set `NLM_F_REPLACE` flag"]
3895 pub fn set_replace(mut self) -> Self {
3896 self.flags |= consts::NLM_F_REPLACE as u16;
3897 self
3898 }
3899 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3900 pub fn set_change(self) -> Self {
3901 self.set_create().set_replace()
3902 }
3903 #[doc = "Set `NLM_F_APPEND` flag"]
3904 pub fn set_append(mut self) -> Self {
3905 self.flags |= consts::NLM_F_APPEND as u16;
3906 self
3907 }
3908 #[doc = "Set `NLM_F_DUMP` flag"]
3909 fn set_dump(mut self) -> Self {
3910 self.flags |= consts::NLM_F_DUMP as u16;
3911 self
3912 }
3913 pub fn op_tcp_diag_dump_request(self, header: &ReqV2) -> RequestOpTcpDiagDumpRequest<'buf> {
3914 let mut res = RequestOpTcpDiagDumpRequest::new(self, header);
3915 res.request.do_writeback(
3916 res.protocol(),
3917 "op-tcp-diag-dump-request",
3918 RequestOpTcpDiagDumpRequest::lookup,
3919 );
3920 res
3921 }
3922 pub fn op_udp_diag_dump_request(self, header: &ReqV2) -> RequestOpUdpDiagDumpRequest<'buf> {
3923 let mut res = RequestOpUdpDiagDumpRequest::new(self, header);
3924 res.request.do_writeback(
3925 res.protocol(),
3926 "op-udp-diag-dump-request",
3927 RequestOpUdpDiagDumpRequest::lookup,
3928 );
3929 res
3930 }
3931}