1#![doc = "Netfilter connection tracking subsystem over nfnetlink\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "conntrack";
17pub const PROTONAME_CSTR: &CStr = c"conntrack";
18pub const PROTONUM: u16 = 12u16;
19#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
20#[derive(Debug, Clone, Copy)]
21pub enum NfCtTcpFlags {
22 WindowScale = 1 << 0,
23 SackPerm = 1 << 1,
24 CloseInit = 1 << 2,
25 BeLiberal = 1 << 3,
26 Unacked = 1 << 4,
27 Maxack = 1 << 5,
28 ChallengeAck = 1 << 6,
29 SimultaneousOpen = 1 << 7,
30}
31impl NfCtTcpFlags {
32 pub fn from_value(value: u64) -> Option<Self> {
33 Some(match value {
34 n if n == 1 << 0 => Self::WindowScale,
35 n if n == 1 << 1 => Self::SackPerm,
36 n if n == 1 << 2 => Self::CloseInit,
37 n if n == 1 << 3 => Self::BeLiberal,
38 n if n == 1 << 4 => Self::Unacked,
39 n if n == 1 << 5 => Self::Maxack,
40 n if n == 1 << 6 => Self::ChallengeAck,
41 n if n == 1 << 7 => Self::SimultaneousOpen,
42 _ => return None,
43 })
44 }
45}
46#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
47#[derive(Debug, Clone, Copy)]
48pub enum NfCtTcpState {
49 None = 0,
50 SynSent = 1,
51 SynRecv = 2,
52 Established = 3,
53 FinWait = 4,
54 CloseWait = 5,
55 LastAck = 6,
56 TimeWait = 7,
57 Close = 8,
58 SynSent2 = 9,
59 Max = 10,
60 Ignore = 11,
61 Retrans = 12,
62 Unack = 13,
63 TimeoutMax = 14,
64}
65impl NfCtTcpState {
66 pub fn from_value(value: u64) -> Option<Self> {
67 Some(match value {
68 0 => Self::None,
69 1 => Self::SynSent,
70 2 => Self::SynRecv,
71 3 => Self::Established,
72 4 => Self::FinWait,
73 5 => Self::CloseWait,
74 6 => Self::LastAck,
75 7 => Self::TimeWait,
76 8 => Self::Close,
77 9 => Self::SynSent2,
78 10 => Self::Max,
79 11 => Self::Ignore,
80 12 => Self::Retrans,
81 13 => Self::Unack,
82 14 => Self::TimeoutMax,
83 _ => return None,
84 })
85 }
86}
87#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
88#[derive(Debug, Clone, Copy)]
89pub enum NfCtSctpState {
90 None = 0,
91 Cloned = 1,
92 CookieWait = 2,
93 CookieEchoed = 3,
94 Established = 4,
95 ShutdownSent = 5,
96 ShutdownReceived = 6,
97 ShutdownAckSent = 7,
98 ShutdownHeartbeatSent = 8,
99}
100impl NfCtSctpState {
101 pub fn from_value(value: u64) -> Option<Self> {
102 Some(match value {
103 0 => Self::None,
104 1 => Self::Cloned,
105 2 => Self::CookieWait,
106 3 => Self::CookieEchoed,
107 4 => Self::Established,
108 5 => Self::ShutdownSent,
109 6 => Self::ShutdownReceived,
110 7 => Self::ShutdownAckSent,
111 8 => Self::ShutdownHeartbeatSent,
112 _ => return None,
113 })
114 }
115}
116#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
117#[derive(Debug, Clone, Copy)]
118pub enum NfCtStatus {
119 Expected = 1 << 0,
120 SeenReply = 1 << 1,
121 Assured = 1 << 2,
122 Confirmed = 1 << 3,
123 SrcNat = 1 << 4,
124 DstNat = 1 << 5,
125 SeqAdj = 1 << 6,
126 SrcNatDone = 1 << 7,
127 DstNatDone = 1 << 8,
128 Dying = 1 << 9,
129 FixedTimeout = 1 << 10,
130 Template = 1 << 11,
131 NatClash = 1 << 12,
132 Helper = 1 << 13,
133 Offload = 1 << 14,
134 HwOffload = 1 << 15,
135}
136impl NfCtStatus {
137 pub fn from_value(value: u64) -> Option<Self> {
138 Some(match value {
139 n if n == 1 << 0 => Self::Expected,
140 n if n == 1 << 1 => Self::SeenReply,
141 n if n == 1 << 2 => Self::Assured,
142 n if n == 1 << 3 => Self::Confirmed,
143 n if n == 1 << 4 => Self::SrcNat,
144 n if n == 1 << 5 => Self::DstNat,
145 n if n == 1 << 6 => Self::SeqAdj,
146 n if n == 1 << 7 => Self::SrcNatDone,
147 n if n == 1 << 8 => Self::DstNatDone,
148 n if n == 1 << 9 => Self::Dying,
149 n if n == 1 << 10 => Self::FixedTimeout,
150 n if n == 1 << 11 => Self::Template,
151 n if n == 1 << 12 => Self::NatClash,
152 n if n == 1 << 13 => Self::Helper,
153 n if n == 1 << 14 => Self::Offload,
154 n if n == 1 << 15 => Self::HwOffload,
155 _ => return None,
156 })
157 }
158}
159#[repr(C, packed(4))]
160pub struct Nfgenmsg {
161 pub nfgen_family: u8,
162 pub version: u8,
163 pub _res_id_be: u16,
164}
165impl Clone for Nfgenmsg {
166 fn clone(&self) -> Self {
167 Self::new_from_array(*self.as_array())
168 }
169}
170#[doc = "Create zero-initialized struct"]
171impl Default for Nfgenmsg {
172 fn default() -> Self {
173 Self::new()
174 }
175}
176impl Nfgenmsg {
177 #[doc = "Create zero-initialized struct"]
178 pub fn new() -> Self {
179 Self::new_from_array([0u8; Self::len()])
180 }
181 #[doc = "Copy from contents from slice"]
182 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
183 if other.len() != Self::len() {
184 return None;
185 }
186 let mut buf = [0u8; Self::len()];
187 buf.clone_from_slice(other);
188 Some(Self::new_from_array(buf))
189 }
190 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
191 pub fn new_from_zeroed(other: &[u8]) -> Self {
192 let mut buf = [0u8; Self::len()];
193 let len = buf.len().min(other.len());
194 buf[..len].clone_from_slice(&other[..len]);
195 Self::new_from_array(buf)
196 }
197 pub fn new_from_array(buf: [u8; 4usize]) -> Self {
198 unsafe { std::mem::transmute(buf) }
199 }
200 pub fn as_slice(&self) -> &[u8] {
201 unsafe {
202 let ptr: *const u8 = std::mem::transmute(self as *const Self);
203 std::slice::from_raw_parts(ptr, Self::len())
204 }
205 }
206 pub fn from_slice(buf: &[u8]) -> &Self {
207 assert!(buf.len() >= Self::len());
208 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
209 unsafe { std::mem::transmute(buf.as_ptr()) }
210 }
211 pub fn as_array(&self) -> &[u8; 4usize] {
212 unsafe { std::mem::transmute(self) }
213 }
214 pub fn from_array(buf: &[u8; 4usize]) -> &Self {
215 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
216 unsafe { std::mem::transmute(buf) }
217 }
218 pub fn into_array(self) -> [u8; 4usize] {
219 unsafe { std::mem::transmute(self) }
220 }
221 pub const fn len() -> usize {
222 const _: () = assert!(std::mem::size_of::<Nfgenmsg>() == 4usize);
223 4usize
224 }
225 pub fn res_id(&self) -> u16 {
226 u16::from_be(self._res_id_be)
227 }
228 pub fn set_res_id(&mut self, value: u16) {
229 self._res_id_be = value.to_be();
230 }
231}
232impl std::fmt::Debug for Nfgenmsg {
233 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 fmt.debug_struct("Nfgenmsg")
235 .field("nfgen_family", &self.nfgen_family)
236 .field("version", &self.version)
237 .field("res_id", &self.res_id())
238 .finish()
239 }
240}
241#[repr(C, packed(4))]
242pub struct NfCtTcpFlagsMask {
243 #[doc = "Associated type: [`NfCtTcpFlags`] (1 bit per enumeration)"]
244 pub flags: u8,
245 #[doc = "Associated type: [`NfCtTcpFlags`] (1 bit per enumeration)"]
246 pub mask: u8,
247}
248impl Clone for NfCtTcpFlagsMask {
249 fn clone(&self) -> Self {
250 Self::new_from_array(*self.as_array())
251 }
252}
253#[doc = "Create zero-initialized struct"]
254impl Default for NfCtTcpFlagsMask {
255 fn default() -> Self {
256 Self::new()
257 }
258}
259impl NfCtTcpFlagsMask {
260 #[doc = "Create zero-initialized struct"]
261 pub fn new() -> Self {
262 Self::new_from_array([0u8; Self::len()])
263 }
264 #[doc = "Copy from contents from slice"]
265 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
266 if other.len() != Self::len() {
267 return None;
268 }
269 let mut buf = [0u8; Self::len()];
270 buf.clone_from_slice(other);
271 Some(Self::new_from_array(buf))
272 }
273 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
274 pub fn new_from_zeroed(other: &[u8]) -> Self {
275 let mut buf = [0u8; Self::len()];
276 let len = buf.len().min(other.len());
277 buf[..len].clone_from_slice(&other[..len]);
278 Self::new_from_array(buf)
279 }
280 pub fn new_from_array(buf: [u8; 2usize]) -> Self {
281 unsafe { std::mem::transmute(buf) }
282 }
283 pub fn as_slice(&self) -> &[u8] {
284 unsafe {
285 let ptr: *const u8 = std::mem::transmute(self as *const Self);
286 std::slice::from_raw_parts(ptr, Self::len())
287 }
288 }
289 pub fn from_slice(buf: &[u8]) -> &Self {
290 assert!(buf.len() >= Self::len());
291 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
292 unsafe { std::mem::transmute(buf.as_ptr()) }
293 }
294 pub fn as_array(&self) -> &[u8; 2usize] {
295 unsafe { std::mem::transmute(self) }
296 }
297 pub fn from_array(buf: &[u8; 2usize]) -> &Self {
298 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
299 unsafe { std::mem::transmute(buf) }
300 }
301 pub fn into_array(self) -> [u8; 2usize] {
302 unsafe { std::mem::transmute(self) }
303 }
304 pub const fn len() -> usize {
305 const _: () = assert!(std::mem::size_of::<NfCtTcpFlagsMask>() == 2usize);
306 2usize
307 }
308}
309impl std::fmt::Debug for NfCtTcpFlagsMask {
310 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311 fmt.debug_struct("NfCtTcpFlagsMask")
312 .field(
313 "flags",
314 &FormatFlags(self.flags.into(), NfCtTcpFlags::from_value),
315 )
316 .field(
317 "mask",
318 &FormatFlags(self.mask.into(), NfCtTcpFlags::from_value),
319 )
320 .finish()
321 }
322}
323#[derive(Clone)]
324pub enum CounterAttrs<'a> {
325 Packets(u64),
326 Bytes(u64),
327 PacketsOld(u32),
328 BytesOld(u32),
329 Pad(&'a [u8]),
330}
331impl<'a> IterableCounterAttrs<'a> {
332 pub fn get_packets(&self) -> Result<u64, ErrorContext> {
333 let mut iter = self.clone();
334 iter.pos = 0;
335 for attr in iter {
336 if let Ok(CounterAttrs::Packets(val)) = attr {
337 return Ok(val);
338 }
339 }
340 Err(ErrorContext::new_missing(
341 "CounterAttrs",
342 "Packets",
343 self.orig_loc,
344 self.buf.as_ptr() as usize,
345 ))
346 }
347 pub fn get_bytes(&self) -> Result<u64, ErrorContext> {
348 let mut iter = self.clone();
349 iter.pos = 0;
350 for attr in iter {
351 if let Ok(CounterAttrs::Bytes(val)) = attr {
352 return Ok(val);
353 }
354 }
355 Err(ErrorContext::new_missing(
356 "CounterAttrs",
357 "Bytes",
358 self.orig_loc,
359 self.buf.as_ptr() as usize,
360 ))
361 }
362 pub fn get_packets_old(&self) -> Result<u32, ErrorContext> {
363 let mut iter = self.clone();
364 iter.pos = 0;
365 for attr in iter {
366 if let Ok(CounterAttrs::PacketsOld(val)) = attr {
367 return Ok(val);
368 }
369 }
370 Err(ErrorContext::new_missing(
371 "CounterAttrs",
372 "PacketsOld",
373 self.orig_loc,
374 self.buf.as_ptr() as usize,
375 ))
376 }
377 pub fn get_bytes_old(&self) -> Result<u32, ErrorContext> {
378 let mut iter = self.clone();
379 iter.pos = 0;
380 for attr in iter {
381 if let Ok(CounterAttrs::BytesOld(val)) = attr {
382 return Ok(val);
383 }
384 }
385 Err(ErrorContext::new_missing(
386 "CounterAttrs",
387 "BytesOld",
388 self.orig_loc,
389 self.buf.as_ptr() as usize,
390 ))
391 }
392 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
393 let mut iter = self.clone();
394 iter.pos = 0;
395 for attr in iter {
396 if let Ok(CounterAttrs::Pad(val)) = attr {
397 return Ok(val);
398 }
399 }
400 Err(ErrorContext::new_missing(
401 "CounterAttrs",
402 "Pad",
403 self.orig_loc,
404 self.buf.as_ptr() as usize,
405 ))
406 }
407}
408impl CounterAttrs<'_> {
409 pub fn new<'a>(buf: &'a [u8]) -> IterableCounterAttrs<'a> {
410 IterableCounterAttrs::with_loc(buf, buf.as_ptr() as usize)
411 }
412 fn attr_from_type(r#type: u16) -> Option<&'static str> {
413 let res = match r#type {
414 1u16 => "Packets",
415 2u16 => "Bytes",
416 3u16 => "PacketsOld",
417 4u16 => "BytesOld",
418 5u16 => "Pad",
419 _ => return None,
420 };
421 Some(res)
422 }
423}
424#[derive(Clone, Copy, Default)]
425pub struct IterableCounterAttrs<'a> {
426 buf: &'a [u8],
427 pos: usize,
428 orig_loc: usize,
429}
430impl<'a> IterableCounterAttrs<'a> {
431 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
432 Self {
433 buf,
434 pos: 0,
435 orig_loc,
436 }
437 }
438 pub fn get_buf(&self) -> &'a [u8] {
439 self.buf
440 }
441}
442impl<'a> Iterator for IterableCounterAttrs<'a> {
443 type Item = Result<CounterAttrs<'a>, ErrorContext>;
444 fn next(&mut self) -> Option<Self::Item> {
445 let mut pos;
446 let mut r#type;
447 loop {
448 pos = self.pos;
449 r#type = None;
450 if self.buf.len() == self.pos {
451 return None;
452 }
453 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
454 self.pos = self.buf.len();
455 break;
456 };
457 r#type = Some(header.r#type);
458 let res = match header.r#type {
459 1u16 => CounterAttrs::Packets({
460 let res = parse_be_u64(next);
461 let Some(val) = res else { break };
462 val
463 }),
464 2u16 => CounterAttrs::Bytes({
465 let res = parse_be_u64(next);
466 let Some(val) = res else { break };
467 val
468 }),
469 3u16 => CounterAttrs::PacketsOld({
470 let res = parse_u32(next);
471 let Some(val) = res else { break };
472 val
473 }),
474 4u16 => CounterAttrs::BytesOld({
475 let res = parse_u32(next);
476 let Some(val) = res else { break };
477 val
478 }),
479 5u16 => CounterAttrs::Pad({
480 let res = Some(next);
481 let Some(val) = res else { break };
482 val
483 }),
484 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
485 n => continue,
486 };
487 return Some(Ok(res));
488 }
489 Some(Err(ErrorContext::new(
490 "CounterAttrs",
491 r#type.and_then(|t| CounterAttrs::attr_from_type(t)),
492 self.orig_loc,
493 self.buf.as_ptr().wrapping_add(pos) as usize,
494 )))
495 }
496}
497impl<'a> std::fmt::Debug for IterableCounterAttrs<'_> {
498 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
499 let mut fmt = f.debug_struct("CounterAttrs");
500 for attr in self.clone() {
501 let attr = match attr {
502 Ok(a) => a,
503 Err(err) => {
504 fmt.finish()?;
505 f.write_str("Err(")?;
506 err.fmt(f)?;
507 return f.write_str(")");
508 }
509 };
510 match attr {
511 CounterAttrs::Packets(val) => fmt.field("Packets", &val),
512 CounterAttrs::Bytes(val) => fmt.field("Bytes", &val),
513 CounterAttrs::PacketsOld(val) => fmt.field("PacketsOld", &val),
514 CounterAttrs::BytesOld(val) => fmt.field("BytesOld", &val),
515 CounterAttrs::Pad(val) => fmt.field("Pad", &val),
516 };
517 }
518 fmt.finish()
519 }
520}
521impl IterableCounterAttrs<'_> {
522 pub fn lookup_attr(
523 &self,
524 offset: usize,
525 missing_type: Option<u16>,
526 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
527 let mut stack = Vec::new();
528 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
529 if missing_type.is_some() && cur == offset {
530 stack.push(("CounterAttrs", offset));
531 return (
532 stack,
533 missing_type.and_then(|t| CounterAttrs::attr_from_type(t)),
534 );
535 }
536 if cur > offset || cur + self.buf.len() < offset {
537 return (stack, None);
538 }
539 let mut attrs = self.clone();
540 let mut last_off = cur + attrs.pos;
541 while let Some(attr) = attrs.next() {
542 let Ok(attr) = attr else { break };
543 match attr {
544 CounterAttrs::Packets(val) => {
545 if last_off == offset {
546 stack.push(("Packets", last_off));
547 break;
548 }
549 }
550 CounterAttrs::Bytes(val) => {
551 if last_off == offset {
552 stack.push(("Bytes", last_off));
553 break;
554 }
555 }
556 CounterAttrs::PacketsOld(val) => {
557 if last_off == offset {
558 stack.push(("PacketsOld", last_off));
559 break;
560 }
561 }
562 CounterAttrs::BytesOld(val) => {
563 if last_off == offset {
564 stack.push(("BytesOld", last_off));
565 break;
566 }
567 }
568 CounterAttrs::Pad(val) => {
569 if last_off == offset {
570 stack.push(("Pad", last_off));
571 break;
572 }
573 }
574 _ => {}
575 };
576 last_off = cur + attrs.pos;
577 }
578 if !stack.is_empty() {
579 stack.push(("CounterAttrs", cur));
580 }
581 (stack, None)
582 }
583}
584#[derive(Clone)]
585pub enum TupleProtoAttrs {
586 #[doc = "l4 protocol number\n"]
587 ProtoNum(u8),
588 #[doc = "l4 source port\n"]
589 ProtoSrcPort(u16),
590 #[doc = "l4 source port\n"]
591 ProtoDstPort(u16),
592 #[doc = "l4 icmp id\n"]
593 ProtoIcmpId(u16),
594 ProtoIcmpType(u8),
595 ProtoIcmpCode(u8),
596 #[doc = "l4 icmp id\n"]
597 ProtoIcmpv6Id(u16),
598 ProtoIcmpv6Type(u8),
599 ProtoIcmpv6Code(u8),
600}
601impl<'a> IterableTupleProtoAttrs<'a> {
602 #[doc = "l4 protocol number\n"]
603 pub fn get_proto_num(&self) -> Result<u8, ErrorContext> {
604 let mut iter = self.clone();
605 iter.pos = 0;
606 for attr in iter {
607 if let Ok(TupleProtoAttrs::ProtoNum(val)) = attr {
608 return Ok(val);
609 }
610 }
611 Err(ErrorContext::new_missing(
612 "TupleProtoAttrs",
613 "ProtoNum",
614 self.orig_loc,
615 self.buf.as_ptr() as usize,
616 ))
617 }
618 #[doc = "l4 source port\n"]
619 pub fn get_proto_src_port(&self) -> Result<u16, ErrorContext> {
620 let mut iter = self.clone();
621 iter.pos = 0;
622 for attr in iter {
623 if let Ok(TupleProtoAttrs::ProtoSrcPort(val)) = attr {
624 return Ok(val);
625 }
626 }
627 Err(ErrorContext::new_missing(
628 "TupleProtoAttrs",
629 "ProtoSrcPort",
630 self.orig_loc,
631 self.buf.as_ptr() as usize,
632 ))
633 }
634 #[doc = "l4 source port\n"]
635 pub fn get_proto_dst_port(&self) -> Result<u16, ErrorContext> {
636 let mut iter = self.clone();
637 iter.pos = 0;
638 for attr in iter {
639 if let Ok(TupleProtoAttrs::ProtoDstPort(val)) = attr {
640 return Ok(val);
641 }
642 }
643 Err(ErrorContext::new_missing(
644 "TupleProtoAttrs",
645 "ProtoDstPort",
646 self.orig_loc,
647 self.buf.as_ptr() as usize,
648 ))
649 }
650 #[doc = "l4 icmp id\n"]
651 pub fn get_proto_icmp_id(&self) -> Result<u16, ErrorContext> {
652 let mut iter = self.clone();
653 iter.pos = 0;
654 for attr in iter {
655 if let Ok(TupleProtoAttrs::ProtoIcmpId(val)) = attr {
656 return Ok(val);
657 }
658 }
659 Err(ErrorContext::new_missing(
660 "TupleProtoAttrs",
661 "ProtoIcmpId",
662 self.orig_loc,
663 self.buf.as_ptr() as usize,
664 ))
665 }
666 pub fn get_proto_icmp_type(&self) -> Result<u8, ErrorContext> {
667 let mut iter = self.clone();
668 iter.pos = 0;
669 for attr in iter {
670 if let Ok(TupleProtoAttrs::ProtoIcmpType(val)) = attr {
671 return Ok(val);
672 }
673 }
674 Err(ErrorContext::new_missing(
675 "TupleProtoAttrs",
676 "ProtoIcmpType",
677 self.orig_loc,
678 self.buf.as_ptr() as usize,
679 ))
680 }
681 pub fn get_proto_icmp_code(&self) -> Result<u8, ErrorContext> {
682 let mut iter = self.clone();
683 iter.pos = 0;
684 for attr in iter {
685 if let Ok(TupleProtoAttrs::ProtoIcmpCode(val)) = attr {
686 return Ok(val);
687 }
688 }
689 Err(ErrorContext::new_missing(
690 "TupleProtoAttrs",
691 "ProtoIcmpCode",
692 self.orig_loc,
693 self.buf.as_ptr() as usize,
694 ))
695 }
696 #[doc = "l4 icmp id\n"]
697 pub fn get_proto_icmpv6_id(&self) -> Result<u16, ErrorContext> {
698 let mut iter = self.clone();
699 iter.pos = 0;
700 for attr in iter {
701 if let Ok(TupleProtoAttrs::ProtoIcmpv6Id(val)) = attr {
702 return Ok(val);
703 }
704 }
705 Err(ErrorContext::new_missing(
706 "TupleProtoAttrs",
707 "ProtoIcmpv6Id",
708 self.orig_loc,
709 self.buf.as_ptr() as usize,
710 ))
711 }
712 pub fn get_proto_icmpv6_type(&self) -> Result<u8, ErrorContext> {
713 let mut iter = self.clone();
714 iter.pos = 0;
715 for attr in iter {
716 if let Ok(TupleProtoAttrs::ProtoIcmpv6Type(val)) = attr {
717 return Ok(val);
718 }
719 }
720 Err(ErrorContext::new_missing(
721 "TupleProtoAttrs",
722 "ProtoIcmpv6Type",
723 self.orig_loc,
724 self.buf.as_ptr() as usize,
725 ))
726 }
727 pub fn get_proto_icmpv6_code(&self) -> Result<u8, ErrorContext> {
728 let mut iter = self.clone();
729 iter.pos = 0;
730 for attr in iter {
731 if let Ok(TupleProtoAttrs::ProtoIcmpv6Code(val)) = attr {
732 return Ok(val);
733 }
734 }
735 Err(ErrorContext::new_missing(
736 "TupleProtoAttrs",
737 "ProtoIcmpv6Code",
738 self.orig_loc,
739 self.buf.as_ptr() as usize,
740 ))
741 }
742}
743impl TupleProtoAttrs {
744 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleProtoAttrs<'a> {
745 IterableTupleProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
746 }
747 fn attr_from_type(r#type: u16) -> Option<&'static str> {
748 let res = match r#type {
749 1u16 => "ProtoNum",
750 2u16 => "ProtoSrcPort",
751 3u16 => "ProtoDstPort",
752 4u16 => "ProtoIcmpId",
753 5u16 => "ProtoIcmpType",
754 6u16 => "ProtoIcmpCode",
755 7u16 => "ProtoIcmpv6Id",
756 8u16 => "ProtoIcmpv6Type",
757 9u16 => "ProtoIcmpv6Code",
758 _ => return None,
759 };
760 Some(res)
761 }
762}
763#[derive(Clone, Copy, Default)]
764pub struct IterableTupleProtoAttrs<'a> {
765 buf: &'a [u8],
766 pos: usize,
767 orig_loc: usize,
768}
769impl<'a> IterableTupleProtoAttrs<'a> {
770 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
771 Self {
772 buf,
773 pos: 0,
774 orig_loc,
775 }
776 }
777 pub fn get_buf(&self) -> &'a [u8] {
778 self.buf
779 }
780}
781impl<'a> Iterator for IterableTupleProtoAttrs<'a> {
782 type Item = Result<TupleProtoAttrs, ErrorContext>;
783 fn next(&mut self) -> Option<Self::Item> {
784 let mut pos;
785 let mut r#type;
786 loop {
787 pos = self.pos;
788 r#type = None;
789 if self.buf.len() == self.pos {
790 return None;
791 }
792 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
793 self.pos = self.buf.len();
794 break;
795 };
796 r#type = Some(header.r#type);
797 let res = match header.r#type {
798 1u16 => TupleProtoAttrs::ProtoNum({
799 let res = parse_u8(next);
800 let Some(val) = res else { break };
801 val
802 }),
803 2u16 => TupleProtoAttrs::ProtoSrcPort({
804 let res = parse_be_u16(next);
805 let Some(val) = res else { break };
806 val
807 }),
808 3u16 => TupleProtoAttrs::ProtoDstPort({
809 let res = parse_be_u16(next);
810 let Some(val) = res else { break };
811 val
812 }),
813 4u16 => TupleProtoAttrs::ProtoIcmpId({
814 let res = parse_be_u16(next);
815 let Some(val) = res else { break };
816 val
817 }),
818 5u16 => TupleProtoAttrs::ProtoIcmpType({
819 let res = parse_u8(next);
820 let Some(val) = res else { break };
821 val
822 }),
823 6u16 => TupleProtoAttrs::ProtoIcmpCode({
824 let res = parse_u8(next);
825 let Some(val) = res else { break };
826 val
827 }),
828 7u16 => TupleProtoAttrs::ProtoIcmpv6Id({
829 let res = parse_be_u16(next);
830 let Some(val) = res else { break };
831 val
832 }),
833 8u16 => TupleProtoAttrs::ProtoIcmpv6Type({
834 let res = parse_u8(next);
835 let Some(val) = res else { break };
836 val
837 }),
838 9u16 => TupleProtoAttrs::ProtoIcmpv6Code({
839 let res = parse_u8(next);
840 let Some(val) = res else { break };
841 val
842 }),
843 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
844 n => continue,
845 };
846 return Some(Ok(res));
847 }
848 Some(Err(ErrorContext::new(
849 "TupleProtoAttrs",
850 r#type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
851 self.orig_loc,
852 self.buf.as_ptr().wrapping_add(pos) as usize,
853 )))
854 }
855}
856impl std::fmt::Debug for IterableTupleProtoAttrs<'_> {
857 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
858 let mut fmt = f.debug_struct("TupleProtoAttrs");
859 for attr in self.clone() {
860 let attr = match attr {
861 Ok(a) => a,
862 Err(err) => {
863 fmt.finish()?;
864 f.write_str("Err(")?;
865 err.fmt(f)?;
866 return f.write_str(")");
867 }
868 };
869 match attr {
870 TupleProtoAttrs::ProtoNum(val) => fmt.field("ProtoNum", &val),
871 TupleProtoAttrs::ProtoSrcPort(val) => fmt.field("ProtoSrcPort", &val),
872 TupleProtoAttrs::ProtoDstPort(val) => fmt.field("ProtoDstPort", &val),
873 TupleProtoAttrs::ProtoIcmpId(val) => fmt.field("ProtoIcmpId", &val),
874 TupleProtoAttrs::ProtoIcmpType(val) => fmt.field("ProtoIcmpType", &val),
875 TupleProtoAttrs::ProtoIcmpCode(val) => fmt.field("ProtoIcmpCode", &val),
876 TupleProtoAttrs::ProtoIcmpv6Id(val) => fmt.field("ProtoIcmpv6Id", &val),
877 TupleProtoAttrs::ProtoIcmpv6Type(val) => fmt.field("ProtoIcmpv6Type", &val),
878 TupleProtoAttrs::ProtoIcmpv6Code(val) => fmt.field("ProtoIcmpv6Code", &val),
879 };
880 }
881 fmt.finish()
882 }
883}
884impl IterableTupleProtoAttrs<'_> {
885 pub fn lookup_attr(
886 &self,
887 offset: usize,
888 missing_type: Option<u16>,
889 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
890 let mut stack = Vec::new();
891 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
892 if missing_type.is_some() && cur == offset {
893 stack.push(("TupleProtoAttrs", offset));
894 return (
895 stack,
896 missing_type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
897 );
898 }
899 if cur > offset || cur + self.buf.len() < offset {
900 return (stack, None);
901 }
902 let mut attrs = self.clone();
903 let mut last_off = cur + attrs.pos;
904 while let Some(attr) = attrs.next() {
905 let Ok(attr) = attr else { break };
906 match attr {
907 TupleProtoAttrs::ProtoNum(val) => {
908 if last_off == offset {
909 stack.push(("ProtoNum", last_off));
910 break;
911 }
912 }
913 TupleProtoAttrs::ProtoSrcPort(val) => {
914 if last_off == offset {
915 stack.push(("ProtoSrcPort", last_off));
916 break;
917 }
918 }
919 TupleProtoAttrs::ProtoDstPort(val) => {
920 if last_off == offset {
921 stack.push(("ProtoDstPort", last_off));
922 break;
923 }
924 }
925 TupleProtoAttrs::ProtoIcmpId(val) => {
926 if last_off == offset {
927 stack.push(("ProtoIcmpId", last_off));
928 break;
929 }
930 }
931 TupleProtoAttrs::ProtoIcmpType(val) => {
932 if last_off == offset {
933 stack.push(("ProtoIcmpType", last_off));
934 break;
935 }
936 }
937 TupleProtoAttrs::ProtoIcmpCode(val) => {
938 if last_off == offset {
939 stack.push(("ProtoIcmpCode", last_off));
940 break;
941 }
942 }
943 TupleProtoAttrs::ProtoIcmpv6Id(val) => {
944 if last_off == offset {
945 stack.push(("ProtoIcmpv6Id", last_off));
946 break;
947 }
948 }
949 TupleProtoAttrs::ProtoIcmpv6Type(val) => {
950 if last_off == offset {
951 stack.push(("ProtoIcmpv6Type", last_off));
952 break;
953 }
954 }
955 TupleProtoAttrs::ProtoIcmpv6Code(val) => {
956 if last_off == offset {
957 stack.push(("ProtoIcmpv6Code", last_off));
958 break;
959 }
960 }
961 _ => {}
962 };
963 last_off = cur + attrs.pos;
964 }
965 if !stack.is_empty() {
966 stack.push(("TupleProtoAttrs", cur));
967 }
968 (stack, None)
969 }
970}
971#[derive(Clone)]
972pub enum TupleIpAttrs {
973 #[doc = "ipv4 source address\n"]
974 IpV4Src(std::net::Ipv4Addr),
975 #[doc = "ipv4 destination address\n"]
976 IpV4Dst(std::net::Ipv4Addr),
977 #[doc = "ipv6 source address\n"]
978 IpV6Src(std::net::Ipv6Addr),
979 #[doc = "ipv6 destination address\n"]
980 IpV6Dst(std::net::Ipv6Addr),
981}
982impl<'a> IterableTupleIpAttrs<'a> {
983 #[doc = "ipv4 source address\n"]
984 pub fn get_ip_v4_src(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
985 let mut iter = self.clone();
986 iter.pos = 0;
987 for attr in iter {
988 if let Ok(TupleIpAttrs::IpV4Src(val)) = attr {
989 return Ok(val);
990 }
991 }
992 Err(ErrorContext::new_missing(
993 "TupleIpAttrs",
994 "IpV4Src",
995 self.orig_loc,
996 self.buf.as_ptr() as usize,
997 ))
998 }
999 #[doc = "ipv4 destination address\n"]
1000 pub fn get_ip_v4_dst(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
1001 let mut iter = self.clone();
1002 iter.pos = 0;
1003 for attr in iter {
1004 if let Ok(TupleIpAttrs::IpV4Dst(val)) = attr {
1005 return Ok(val);
1006 }
1007 }
1008 Err(ErrorContext::new_missing(
1009 "TupleIpAttrs",
1010 "IpV4Dst",
1011 self.orig_loc,
1012 self.buf.as_ptr() as usize,
1013 ))
1014 }
1015 #[doc = "ipv6 source address\n"]
1016 pub fn get_ip_v6_src(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
1017 let mut iter = self.clone();
1018 iter.pos = 0;
1019 for attr in iter {
1020 if let Ok(TupleIpAttrs::IpV6Src(val)) = attr {
1021 return Ok(val);
1022 }
1023 }
1024 Err(ErrorContext::new_missing(
1025 "TupleIpAttrs",
1026 "IpV6Src",
1027 self.orig_loc,
1028 self.buf.as_ptr() as usize,
1029 ))
1030 }
1031 #[doc = "ipv6 destination address\n"]
1032 pub fn get_ip_v6_dst(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
1033 let mut iter = self.clone();
1034 iter.pos = 0;
1035 for attr in iter {
1036 if let Ok(TupleIpAttrs::IpV6Dst(val)) = attr {
1037 return Ok(val);
1038 }
1039 }
1040 Err(ErrorContext::new_missing(
1041 "TupleIpAttrs",
1042 "IpV6Dst",
1043 self.orig_loc,
1044 self.buf.as_ptr() as usize,
1045 ))
1046 }
1047}
1048impl TupleIpAttrs {
1049 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleIpAttrs<'a> {
1050 IterableTupleIpAttrs::with_loc(buf, buf.as_ptr() as usize)
1051 }
1052 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1053 let res = match r#type {
1054 1u16 => "IpV4Src",
1055 2u16 => "IpV4Dst",
1056 3u16 => "IpV6Src",
1057 4u16 => "IpV6Dst",
1058 _ => return None,
1059 };
1060 Some(res)
1061 }
1062}
1063#[derive(Clone, Copy, Default)]
1064pub struct IterableTupleIpAttrs<'a> {
1065 buf: &'a [u8],
1066 pos: usize,
1067 orig_loc: usize,
1068}
1069impl<'a> IterableTupleIpAttrs<'a> {
1070 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1071 Self {
1072 buf,
1073 pos: 0,
1074 orig_loc,
1075 }
1076 }
1077 pub fn get_buf(&self) -> &'a [u8] {
1078 self.buf
1079 }
1080}
1081impl<'a> Iterator for IterableTupleIpAttrs<'a> {
1082 type Item = Result<TupleIpAttrs, ErrorContext>;
1083 fn next(&mut self) -> Option<Self::Item> {
1084 let mut pos;
1085 let mut r#type;
1086 loop {
1087 pos = self.pos;
1088 r#type = None;
1089 if self.buf.len() == self.pos {
1090 return None;
1091 }
1092 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1093 self.pos = self.buf.len();
1094 break;
1095 };
1096 r#type = Some(header.r#type);
1097 let res = match header.r#type {
1098 1u16 => TupleIpAttrs::IpV4Src({
1099 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
1100 let Some(val) = res else { break };
1101 val
1102 }),
1103 2u16 => TupleIpAttrs::IpV4Dst({
1104 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
1105 let Some(val) = res else { break };
1106 val
1107 }),
1108 3u16 => TupleIpAttrs::IpV6Src({
1109 let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
1110 let Some(val) = res else { break };
1111 val
1112 }),
1113 4u16 => TupleIpAttrs::IpV6Dst({
1114 let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
1115 let Some(val) = res else { break };
1116 val
1117 }),
1118 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1119 n => continue,
1120 };
1121 return Some(Ok(res));
1122 }
1123 Some(Err(ErrorContext::new(
1124 "TupleIpAttrs",
1125 r#type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
1126 self.orig_loc,
1127 self.buf.as_ptr().wrapping_add(pos) as usize,
1128 )))
1129 }
1130}
1131impl std::fmt::Debug for IterableTupleIpAttrs<'_> {
1132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1133 let mut fmt = f.debug_struct("TupleIpAttrs");
1134 for attr in self.clone() {
1135 let attr = match attr {
1136 Ok(a) => a,
1137 Err(err) => {
1138 fmt.finish()?;
1139 f.write_str("Err(")?;
1140 err.fmt(f)?;
1141 return f.write_str(")");
1142 }
1143 };
1144 match attr {
1145 TupleIpAttrs::IpV4Src(val) => fmt.field("IpV4Src", &val),
1146 TupleIpAttrs::IpV4Dst(val) => fmt.field("IpV4Dst", &val),
1147 TupleIpAttrs::IpV6Src(val) => fmt.field("IpV6Src", &val),
1148 TupleIpAttrs::IpV6Dst(val) => fmt.field("IpV6Dst", &val),
1149 };
1150 }
1151 fmt.finish()
1152 }
1153}
1154impl IterableTupleIpAttrs<'_> {
1155 pub fn lookup_attr(
1156 &self,
1157 offset: usize,
1158 missing_type: Option<u16>,
1159 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1160 let mut stack = Vec::new();
1161 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1162 if missing_type.is_some() && cur == offset {
1163 stack.push(("TupleIpAttrs", offset));
1164 return (
1165 stack,
1166 missing_type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
1167 );
1168 }
1169 if cur > offset || cur + self.buf.len() < offset {
1170 return (stack, None);
1171 }
1172 let mut attrs = self.clone();
1173 let mut last_off = cur + attrs.pos;
1174 while let Some(attr) = attrs.next() {
1175 let Ok(attr) = attr else { break };
1176 match attr {
1177 TupleIpAttrs::IpV4Src(val) => {
1178 if last_off == offset {
1179 stack.push(("IpV4Src", last_off));
1180 break;
1181 }
1182 }
1183 TupleIpAttrs::IpV4Dst(val) => {
1184 if last_off == offset {
1185 stack.push(("IpV4Dst", last_off));
1186 break;
1187 }
1188 }
1189 TupleIpAttrs::IpV6Src(val) => {
1190 if last_off == offset {
1191 stack.push(("IpV6Src", last_off));
1192 break;
1193 }
1194 }
1195 TupleIpAttrs::IpV6Dst(val) => {
1196 if last_off == offset {
1197 stack.push(("IpV6Dst", last_off));
1198 break;
1199 }
1200 }
1201 _ => {}
1202 };
1203 last_off = cur + attrs.pos;
1204 }
1205 if !stack.is_empty() {
1206 stack.push(("TupleIpAttrs", cur));
1207 }
1208 (stack, None)
1209 }
1210}
1211#[derive(Clone)]
1212pub enum TupleAttrs<'a> {
1213 #[doc = "conntrack l3 information\n"]
1214 TupleIp(IterableTupleIpAttrs<'a>),
1215 #[doc = "conntrack l4 information\n"]
1216 TupleProto(IterableTupleProtoAttrs<'a>),
1217 #[doc = "conntrack zone id\n"]
1218 TupleZone(u16),
1219}
1220impl<'a> IterableTupleAttrs<'a> {
1221 #[doc = "conntrack l3 information\n"]
1222 pub fn get_tuple_ip(&self) -> Result<IterableTupleIpAttrs<'a>, ErrorContext> {
1223 let mut iter = self.clone();
1224 iter.pos = 0;
1225 for attr in iter {
1226 if let Ok(TupleAttrs::TupleIp(val)) = attr {
1227 return Ok(val);
1228 }
1229 }
1230 Err(ErrorContext::new_missing(
1231 "TupleAttrs",
1232 "TupleIp",
1233 self.orig_loc,
1234 self.buf.as_ptr() as usize,
1235 ))
1236 }
1237 #[doc = "conntrack l4 information\n"]
1238 pub fn get_tuple_proto(&self) -> Result<IterableTupleProtoAttrs<'a>, ErrorContext> {
1239 let mut iter = self.clone();
1240 iter.pos = 0;
1241 for attr in iter {
1242 if let Ok(TupleAttrs::TupleProto(val)) = attr {
1243 return Ok(val);
1244 }
1245 }
1246 Err(ErrorContext::new_missing(
1247 "TupleAttrs",
1248 "TupleProto",
1249 self.orig_loc,
1250 self.buf.as_ptr() as usize,
1251 ))
1252 }
1253 #[doc = "conntrack zone id\n"]
1254 pub fn get_tuple_zone(&self) -> Result<u16, ErrorContext> {
1255 let mut iter = self.clone();
1256 iter.pos = 0;
1257 for attr in iter {
1258 if let Ok(TupleAttrs::TupleZone(val)) = attr {
1259 return Ok(val);
1260 }
1261 }
1262 Err(ErrorContext::new_missing(
1263 "TupleAttrs",
1264 "TupleZone",
1265 self.orig_loc,
1266 self.buf.as_ptr() as usize,
1267 ))
1268 }
1269}
1270impl TupleAttrs<'_> {
1271 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleAttrs<'a> {
1272 IterableTupleAttrs::with_loc(buf, buf.as_ptr() as usize)
1273 }
1274 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1275 let res = match r#type {
1276 1u16 => "TupleIp",
1277 2u16 => "TupleProto",
1278 3u16 => "TupleZone",
1279 _ => return None,
1280 };
1281 Some(res)
1282 }
1283}
1284#[derive(Clone, Copy, Default)]
1285pub struct IterableTupleAttrs<'a> {
1286 buf: &'a [u8],
1287 pos: usize,
1288 orig_loc: usize,
1289}
1290impl<'a> IterableTupleAttrs<'a> {
1291 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1292 Self {
1293 buf,
1294 pos: 0,
1295 orig_loc,
1296 }
1297 }
1298 pub fn get_buf(&self) -> &'a [u8] {
1299 self.buf
1300 }
1301}
1302impl<'a> Iterator for IterableTupleAttrs<'a> {
1303 type Item = Result<TupleAttrs<'a>, ErrorContext>;
1304 fn next(&mut self) -> Option<Self::Item> {
1305 let mut pos;
1306 let mut r#type;
1307 loop {
1308 pos = self.pos;
1309 r#type = None;
1310 if self.buf.len() == self.pos {
1311 return None;
1312 }
1313 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1314 self.pos = self.buf.len();
1315 break;
1316 };
1317 r#type = Some(header.r#type);
1318 let res = match header.r#type {
1319 1u16 => TupleAttrs::TupleIp({
1320 let res = Some(IterableTupleIpAttrs::with_loc(next, self.orig_loc));
1321 let Some(val) = res else { break };
1322 val
1323 }),
1324 2u16 => TupleAttrs::TupleProto({
1325 let res = Some(IterableTupleProtoAttrs::with_loc(next, self.orig_loc));
1326 let Some(val) = res else { break };
1327 val
1328 }),
1329 3u16 => TupleAttrs::TupleZone({
1330 let res = parse_be_u16(next);
1331 let Some(val) = res else { break };
1332 val
1333 }),
1334 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1335 n => continue,
1336 };
1337 return Some(Ok(res));
1338 }
1339 Some(Err(ErrorContext::new(
1340 "TupleAttrs",
1341 r#type.and_then(|t| TupleAttrs::attr_from_type(t)),
1342 self.orig_loc,
1343 self.buf.as_ptr().wrapping_add(pos) as usize,
1344 )))
1345 }
1346}
1347impl<'a> std::fmt::Debug for IterableTupleAttrs<'_> {
1348 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1349 let mut fmt = f.debug_struct("TupleAttrs");
1350 for attr in self.clone() {
1351 let attr = match attr {
1352 Ok(a) => a,
1353 Err(err) => {
1354 fmt.finish()?;
1355 f.write_str("Err(")?;
1356 err.fmt(f)?;
1357 return f.write_str(")");
1358 }
1359 };
1360 match attr {
1361 TupleAttrs::TupleIp(val) => fmt.field("TupleIp", &val),
1362 TupleAttrs::TupleProto(val) => fmt.field("TupleProto", &val),
1363 TupleAttrs::TupleZone(val) => fmt.field("TupleZone", &val),
1364 };
1365 }
1366 fmt.finish()
1367 }
1368}
1369impl IterableTupleAttrs<'_> {
1370 pub fn lookup_attr(
1371 &self,
1372 offset: usize,
1373 missing_type: Option<u16>,
1374 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1375 let mut stack = Vec::new();
1376 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1377 if missing_type.is_some() && cur == offset {
1378 stack.push(("TupleAttrs", offset));
1379 return (
1380 stack,
1381 missing_type.and_then(|t| TupleAttrs::attr_from_type(t)),
1382 );
1383 }
1384 if cur > offset || cur + self.buf.len() < offset {
1385 return (stack, None);
1386 }
1387 let mut attrs = self.clone();
1388 let mut last_off = cur + attrs.pos;
1389 let mut missing = None;
1390 while let Some(attr) = attrs.next() {
1391 let Ok(attr) = attr else { break };
1392 match attr {
1393 TupleAttrs::TupleIp(val) => {
1394 (stack, missing) = val.lookup_attr(offset, missing_type);
1395 if !stack.is_empty() {
1396 break;
1397 }
1398 }
1399 TupleAttrs::TupleProto(val) => {
1400 (stack, missing) = val.lookup_attr(offset, missing_type);
1401 if !stack.is_empty() {
1402 break;
1403 }
1404 }
1405 TupleAttrs::TupleZone(val) => {
1406 if last_off == offset {
1407 stack.push(("TupleZone", last_off));
1408 break;
1409 }
1410 }
1411 _ => {}
1412 };
1413 last_off = cur + attrs.pos;
1414 }
1415 if !stack.is_empty() {
1416 stack.push(("TupleAttrs", cur));
1417 }
1418 (stack, missing)
1419 }
1420}
1421#[derive(Clone)]
1422pub enum ProtoinfoTcpAttrs {
1423 #[doc = "tcp connection state\n\nAssociated type: [`NfCtTcpState`] (enum)"]
1424 TcpState(u8),
1425 #[doc = "window scaling factor in original direction\n"]
1426 TcpWscaleOriginal(u8),
1427 #[doc = "window scaling factor in reply direction\n"]
1428 TcpWscaleReply(u8),
1429 TcpFlagsOriginal(NfCtTcpFlagsMask),
1430 TcpFlagsReply(NfCtTcpFlagsMask),
1431}
1432impl<'a> IterableProtoinfoTcpAttrs<'a> {
1433 #[doc = "tcp connection state\n\nAssociated type: [`NfCtTcpState`] (enum)"]
1434 pub fn get_tcp_state(&self) -> Result<u8, ErrorContext> {
1435 let mut iter = self.clone();
1436 iter.pos = 0;
1437 for attr in iter {
1438 if let Ok(ProtoinfoTcpAttrs::TcpState(val)) = attr {
1439 return Ok(val);
1440 }
1441 }
1442 Err(ErrorContext::new_missing(
1443 "ProtoinfoTcpAttrs",
1444 "TcpState",
1445 self.orig_loc,
1446 self.buf.as_ptr() as usize,
1447 ))
1448 }
1449 #[doc = "window scaling factor in original direction\n"]
1450 pub fn get_tcp_wscale_original(&self) -> Result<u8, ErrorContext> {
1451 let mut iter = self.clone();
1452 iter.pos = 0;
1453 for attr in iter {
1454 if let Ok(ProtoinfoTcpAttrs::TcpWscaleOriginal(val)) = attr {
1455 return Ok(val);
1456 }
1457 }
1458 Err(ErrorContext::new_missing(
1459 "ProtoinfoTcpAttrs",
1460 "TcpWscaleOriginal",
1461 self.orig_loc,
1462 self.buf.as_ptr() as usize,
1463 ))
1464 }
1465 #[doc = "window scaling factor in reply direction\n"]
1466 pub fn get_tcp_wscale_reply(&self) -> Result<u8, ErrorContext> {
1467 let mut iter = self.clone();
1468 iter.pos = 0;
1469 for attr in iter {
1470 if let Ok(ProtoinfoTcpAttrs::TcpWscaleReply(val)) = attr {
1471 return Ok(val);
1472 }
1473 }
1474 Err(ErrorContext::new_missing(
1475 "ProtoinfoTcpAttrs",
1476 "TcpWscaleReply",
1477 self.orig_loc,
1478 self.buf.as_ptr() as usize,
1479 ))
1480 }
1481 pub fn get_tcp_flags_original(&self) -> Result<NfCtTcpFlagsMask, ErrorContext> {
1482 let mut iter = self.clone();
1483 iter.pos = 0;
1484 for attr in iter {
1485 if let Ok(ProtoinfoTcpAttrs::TcpFlagsOriginal(val)) = attr {
1486 return Ok(val);
1487 }
1488 }
1489 Err(ErrorContext::new_missing(
1490 "ProtoinfoTcpAttrs",
1491 "TcpFlagsOriginal",
1492 self.orig_loc,
1493 self.buf.as_ptr() as usize,
1494 ))
1495 }
1496 pub fn get_tcp_flags_reply(&self) -> Result<NfCtTcpFlagsMask, ErrorContext> {
1497 let mut iter = self.clone();
1498 iter.pos = 0;
1499 for attr in iter {
1500 if let Ok(ProtoinfoTcpAttrs::TcpFlagsReply(val)) = attr {
1501 return Ok(val);
1502 }
1503 }
1504 Err(ErrorContext::new_missing(
1505 "ProtoinfoTcpAttrs",
1506 "TcpFlagsReply",
1507 self.orig_loc,
1508 self.buf.as_ptr() as usize,
1509 ))
1510 }
1511}
1512impl ProtoinfoTcpAttrs {
1513 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoTcpAttrs<'a> {
1514 IterableProtoinfoTcpAttrs::with_loc(buf, buf.as_ptr() as usize)
1515 }
1516 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1517 let res = match r#type {
1518 1u16 => "TcpState",
1519 2u16 => "TcpWscaleOriginal",
1520 3u16 => "TcpWscaleReply",
1521 4u16 => "TcpFlagsOriginal",
1522 5u16 => "TcpFlagsReply",
1523 _ => return None,
1524 };
1525 Some(res)
1526 }
1527}
1528#[derive(Clone, Copy, Default)]
1529pub struct IterableProtoinfoTcpAttrs<'a> {
1530 buf: &'a [u8],
1531 pos: usize,
1532 orig_loc: usize,
1533}
1534impl<'a> IterableProtoinfoTcpAttrs<'a> {
1535 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1536 Self {
1537 buf,
1538 pos: 0,
1539 orig_loc,
1540 }
1541 }
1542 pub fn get_buf(&self) -> &'a [u8] {
1543 self.buf
1544 }
1545}
1546impl<'a> Iterator for IterableProtoinfoTcpAttrs<'a> {
1547 type Item = Result<ProtoinfoTcpAttrs, ErrorContext>;
1548 fn next(&mut self) -> Option<Self::Item> {
1549 let mut pos;
1550 let mut r#type;
1551 loop {
1552 pos = self.pos;
1553 r#type = None;
1554 if self.buf.len() == self.pos {
1555 return None;
1556 }
1557 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1558 self.pos = self.buf.len();
1559 break;
1560 };
1561 r#type = Some(header.r#type);
1562 let res = match header.r#type {
1563 1u16 => ProtoinfoTcpAttrs::TcpState({
1564 let res = parse_u8(next);
1565 let Some(val) = res else { break };
1566 val
1567 }),
1568 2u16 => ProtoinfoTcpAttrs::TcpWscaleOriginal({
1569 let res = parse_u8(next);
1570 let Some(val) = res else { break };
1571 val
1572 }),
1573 3u16 => ProtoinfoTcpAttrs::TcpWscaleReply({
1574 let res = parse_u8(next);
1575 let Some(val) = res else { break };
1576 val
1577 }),
1578 4u16 => ProtoinfoTcpAttrs::TcpFlagsOriginal({
1579 let res = Some(NfCtTcpFlagsMask::new_from_zeroed(next));
1580 let Some(val) = res else { break };
1581 val
1582 }),
1583 5u16 => ProtoinfoTcpAttrs::TcpFlagsReply({
1584 let res = Some(NfCtTcpFlagsMask::new_from_zeroed(next));
1585 let Some(val) = res else { break };
1586 val
1587 }),
1588 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1589 n => continue,
1590 };
1591 return Some(Ok(res));
1592 }
1593 Some(Err(ErrorContext::new(
1594 "ProtoinfoTcpAttrs",
1595 r#type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1596 self.orig_loc,
1597 self.buf.as_ptr().wrapping_add(pos) as usize,
1598 )))
1599 }
1600}
1601impl std::fmt::Debug for IterableProtoinfoTcpAttrs<'_> {
1602 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1603 let mut fmt = f.debug_struct("ProtoinfoTcpAttrs");
1604 for attr in self.clone() {
1605 let attr = match attr {
1606 Ok(a) => a,
1607 Err(err) => {
1608 fmt.finish()?;
1609 f.write_str("Err(")?;
1610 err.fmt(f)?;
1611 return f.write_str(")");
1612 }
1613 };
1614 match attr {
1615 ProtoinfoTcpAttrs::TcpState(val) => fmt.field(
1616 "TcpState",
1617 &FormatEnum(val.into(), NfCtTcpState::from_value),
1618 ),
1619 ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => fmt.field("TcpWscaleOriginal", &val),
1620 ProtoinfoTcpAttrs::TcpWscaleReply(val) => fmt.field("TcpWscaleReply", &val),
1621 ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => fmt.field("TcpFlagsOriginal", &val),
1622 ProtoinfoTcpAttrs::TcpFlagsReply(val) => fmt.field("TcpFlagsReply", &val),
1623 };
1624 }
1625 fmt.finish()
1626 }
1627}
1628impl IterableProtoinfoTcpAttrs<'_> {
1629 pub fn lookup_attr(
1630 &self,
1631 offset: usize,
1632 missing_type: Option<u16>,
1633 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1634 let mut stack = Vec::new();
1635 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1636 if missing_type.is_some() && cur == offset {
1637 stack.push(("ProtoinfoTcpAttrs", offset));
1638 return (
1639 stack,
1640 missing_type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1641 );
1642 }
1643 if cur > offset || cur + self.buf.len() < offset {
1644 return (stack, None);
1645 }
1646 let mut attrs = self.clone();
1647 let mut last_off = cur + attrs.pos;
1648 while let Some(attr) = attrs.next() {
1649 let Ok(attr) = attr else { break };
1650 match attr {
1651 ProtoinfoTcpAttrs::TcpState(val) => {
1652 if last_off == offset {
1653 stack.push(("TcpState", last_off));
1654 break;
1655 }
1656 }
1657 ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => {
1658 if last_off == offset {
1659 stack.push(("TcpWscaleOriginal", last_off));
1660 break;
1661 }
1662 }
1663 ProtoinfoTcpAttrs::TcpWscaleReply(val) => {
1664 if last_off == offset {
1665 stack.push(("TcpWscaleReply", last_off));
1666 break;
1667 }
1668 }
1669 ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => {
1670 if last_off == offset {
1671 stack.push(("TcpFlagsOriginal", last_off));
1672 break;
1673 }
1674 }
1675 ProtoinfoTcpAttrs::TcpFlagsReply(val) => {
1676 if last_off == offset {
1677 stack.push(("TcpFlagsReply", last_off));
1678 break;
1679 }
1680 }
1681 _ => {}
1682 };
1683 last_off = cur + attrs.pos;
1684 }
1685 if !stack.is_empty() {
1686 stack.push(("ProtoinfoTcpAttrs", cur));
1687 }
1688 (stack, None)
1689 }
1690}
1691#[derive(Clone)]
1692pub enum ProtoinfoDccpAttrs<'a> {
1693 #[doc = "dccp connection state\n"]
1694 DccpState(u8),
1695 DccpRole(u8),
1696 DccpHandshakeSeq(u64),
1697 DccpPad(&'a [u8]),
1698}
1699impl<'a> IterableProtoinfoDccpAttrs<'a> {
1700 #[doc = "dccp connection state\n"]
1701 pub fn get_dccp_state(&self) -> Result<u8, ErrorContext> {
1702 let mut iter = self.clone();
1703 iter.pos = 0;
1704 for attr in iter {
1705 if let Ok(ProtoinfoDccpAttrs::DccpState(val)) = attr {
1706 return Ok(val);
1707 }
1708 }
1709 Err(ErrorContext::new_missing(
1710 "ProtoinfoDccpAttrs",
1711 "DccpState",
1712 self.orig_loc,
1713 self.buf.as_ptr() as usize,
1714 ))
1715 }
1716 pub fn get_dccp_role(&self) -> Result<u8, ErrorContext> {
1717 let mut iter = self.clone();
1718 iter.pos = 0;
1719 for attr in iter {
1720 if let Ok(ProtoinfoDccpAttrs::DccpRole(val)) = attr {
1721 return Ok(val);
1722 }
1723 }
1724 Err(ErrorContext::new_missing(
1725 "ProtoinfoDccpAttrs",
1726 "DccpRole",
1727 self.orig_loc,
1728 self.buf.as_ptr() as usize,
1729 ))
1730 }
1731 pub fn get_dccp_handshake_seq(&self) -> Result<u64, ErrorContext> {
1732 let mut iter = self.clone();
1733 iter.pos = 0;
1734 for attr in iter {
1735 if let Ok(ProtoinfoDccpAttrs::DccpHandshakeSeq(val)) = attr {
1736 return Ok(val);
1737 }
1738 }
1739 Err(ErrorContext::new_missing(
1740 "ProtoinfoDccpAttrs",
1741 "DccpHandshakeSeq",
1742 self.orig_loc,
1743 self.buf.as_ptr() as usize,
1744 ))
1745 }
1746 pub fn get_dccp_pad(&self) -> Result<&'a [u8], ErrorContext> {
1747 let mut iter = self.clone();
1748 iter.pos = 0;
1749 for attr in iter {
1750 if let Ok(ProtoinfoDccpAttrs::DccpPad(val)) = attr {
1751 return Ok(val);
1752 }
1753 }
1754 Err(ErrorContext::new_missing(
1755 "ProtoinfoDccpAttrs",
1756 "DccpPad",
1757 self.orig_loc,
1758 self.buf.as_ptr() as usize,
1759 ))
1760 }
1761}
1762impl ProtoinfoDccpAttrs<'_> {
1763 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoDccpAttrs<'a> {
1764 IterableProtoinfoDccpAttrs::with_loc(buf, buf.as_ptr() as usize)
1765 }
1766 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1767 let res = match r#type {
1768 1u16 => "DccpState",
1769 2u16 => "DccpRole",
1770 3u16 => "DccpHandshakeSeq",
1771 4u16 => "DccpPad",
1772 _ => return None,
1773 };
1774 Some(res)
1775 }
1776}
1777#[derive(Clone, Copy, Default)]
1778pub struct IterableProtoinfoDccpAttrs<'a> {
1779 buf: &'a [u8],
1780 pos: usize,
1781 orig_loc: usize,
1782}
1783impl<'a> IterableProtoinfoDccpAttrs<'a> {
1784 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1785 Self {
1786 buf,
1787 pos: 0,
1788 orig_loc,
1789 }
1790 }
1791 pub fn get_buf(&self) -> &'a [u8] {
1792 self.buf
1793 }
1794}
1795impl<'a> Iterator for IterableProtoinfoDccpAttrs<'a> {
1796 type Item = Result<ProtoinfoDccpAttrs<'a>, ErrorContext>;
1797 fn next(&mut self) -> Option<Self::Item> {
1798 let mut pos;
1799 let mut r#type;
1800 loop {
1801 pos = self.pos;
1802 r#type = None;
1803 if self.buf.len() == self.pos {
1804 return None;
1805 }
1806 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1807 self.pos = self.buf.len();
1808 break;
1809 };
1810 r#type = Some(header.r#type);
1811 let res = match header.r#type {
1812 1u16 => ProtoinfoDccpAttrs::DccpState({
1813 let res = parse_u8(next);
1814 let Some(val) = res else { break };
1815 val
1816 }),
1817 2u16 => ProtoinfoDccpAttrs::DccpRole({
1818 let res = parse_u8(next);
1819 let Some(val) = res else { break };
1820 val
1821 }),
1822 3u16 => ProtoinfoDccpAttrs::DccpHandshakeSeq({
1823 let res = parse_be_u64(next);
1824 let Some(val) = res else { break };
1825 val
1826 }),
1827 4u16 => ProtoinfoDccpAttrs::DccpPad({
1828 let res = Some(next);
1829 let Some(val) = res else { break };
1830 val
1831 }),
1832 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1833 n => continue,
1834 };
1835 return Some(Ok(res));
1836 }
1837 Some(Err(ErrorContext::new(
1838 "ProtoinfoDccpAttrs",
1839 r#type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1840 self.orig_loc,
1841 self.buf.as_ptr().wrapping_add(pos) as usize,
1842 )))
1843 }
1844}
1845impl<'a> std::fmt::Debug for IterableProtoinfoDccpAttrs<'_> {
1846 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1847 let mut fmt = f.debug_struct("ProtoinfoDccpAttrs");
1848 for attr in self.clone() {
1849 let attr = match attr {
1850 Ok(a) => a,
1851 Err(err) => {
1852 fmt.finish()?;
1853 f.write_str("Err(")?;
1854 err.fmt(f)?;
1855 return f.write_str(")");
1856 }
1857 };
1858 match attr {
1859 ProtoinfoDccpAttrs::DccpState(val) => fmt.field("DccpState", &val),
1860 ProtoinfoDccpAttrs::DccpRole(val) => fmt.field("DccpRole", &val),
1861 ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => fmt.field("DccpHandshakeSeq", &val),
1862 ProtoinfoDccpAttrs::DccpPad(val) => fmt.field("DccpPad", &val),
1863 };
1864 }
1865 fmt.finish()
1866 }
1867}
1868impl IterableProtoinfoDccpAttrs<'_> {
1869 pub fn lookup_attr(
1870 &self,
1871 offset: usize,
1872 missing_type: Option<u16>,
1873 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1874 let mut stack = Vec::new();
1875 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1876 if missing_type.is_some() && cur == offset {
1877 stack.push(("ProtoinfoDccpAttrs", offset));
1878 return (
1879 stack,
1880 missing_type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1881 );
1882 }
1883 if cur > offset || cur + self.buf.len() < offset {
1884 return (stack, None);
1885 }
1886 let mut attrs = self.clone();
1887 let mut last_off = cur + attrs.pos;
1888 while let Some(attr) = attrs.next() {
1889 let Ok(attr) = attr else { break };
1890 match attr {
1891 ProtoinfoDccpAttrs::DccpState(val) => {
1892 if last_off == offset {
1893 stack.push(("DccpState", last_off));
1894 break;
1895 }
1896 }
1897 ProtoinfoDccpAttrs::DccpRole(val) => {
1898 if last_off == offset {
1899 stack.push(("DccpRole", last_off));
1900 break;
1901 }
1902 }
1903 ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => {
1904 if last_off == offset {
1905 stack.push(("DccpHandshakeSeq", last_off));
1906 break;
1907 }
1908 }
1909 ProtoinfoDccpAttrs::DccpPad(val) => {
1910 if last_off == offset {
1911 stack.push(("DccpPad", last_off));
1912 break;
1913 }
1914 }
1915 _ => {}
1916 };
1917 last_off = cur + attrs.pos;
1918 }
1919 if !stack.is_empty() {
1920 stack.push(("ProtoinfoDccpAttrs", cur));
1921 }
1922 (stack, None)
1923 }
1924}
1925#[derive(Clone)]
1926pub enum ProtoinfoSctpAttrs {
1927 #[doc = "sctp connection state\n\nAssociated type: [`NfCtSctpState`] (enum)"]
1928 SctpState(u8),
1929 VtagOriginal(u32),
1930 VtagReply(u32),
1931}
1932impl<'a> IterableProtoinfoSctpAttrs<'a> {
1933 #[doc = "sctp connection state\n\nAssociated type: [`NfCtSctpState`] (enum)"]
1934 pub fn get_sctp_state(&self) -> Result<u8, ErrorContext> {
1935 let mut iter = self.clone();
1936 iter.pos = 0;
1937 for attr in iter {
1938 if let Ok(ProtoinfoSctpAttrs::SctpState(val)) = attr {
1939 return Ok(val);
1940 }
1941 }
1942 Err(ErrorContext::new_missing(
1943 "ProtoinfoSctpAttrs",
1944 "SctpState",
1945 self.orig_loc,
1946 self.buf.as_ptr() as usize,
1947 ))
1948 }
1949 pub fn get_vtag_original(&self) -> Result<u32, ErrorContext> {
1950 let mut iter = self.clone();
1951 iter.pos = 0;
1952 for attr in iter {
1953 if let Ok(ProtoinfoSctpAttrs::VtagOriginal(val)) = attr {
1954 return Ok(val);
1955 }
1956 }
1957 Err(ErrorContext::new_missing(
1958 "ProtoinfoSctpAttrs",
1959 "VtagOriginal",
1960 self.orig_loc,
1961 self.buf.as_ptr() as usize,
1962 ))
1963 }
1964 pub fn get_vtag_reply(&self) -> Result<u32, ErrorContext> {
1965 let mut iter = self.clone();
1966 iter.pos = 0;
1967 for attr in iter {
1968 if let Ok(ProtoinfoSctpAttrs::VtagReply(val)) = attr {
1969 return Ok(val);
1970 }
1971 }
1972 Err(ErrorContext::new_missing(
1973 "ProtoinfoSctpAttrs",
1974 "VtagReply",
1975 self.orig_loc,
1976 self.buf.as_ptr() as usize,
1977 ))
1978 }
1979}
1980impl ProtoinfoSctpAttrs {
1981 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoSctpAttrs<'a> {
1982 IterableProtoinfoSctpAttrs::with_loc(buf, buf.as_ptr() as usize)
1983 }
1984 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1985 let res = match r#type {
1986 1u16 => "SctpState",
1987 2u16 => "VtagOriginal",
1988 3u16 => "VtagReply",
1989 _ => return None,
1990 };
1991 Some(res)
1992 }
1993}
1994#[derive(Clone, Copy, Default)]
1995pub struct IterableProtoinfoSctpAttrs<'a> {
1996 buf: &'a [u8],
1997 pos: usize,
1998 orig_loc: usize,
1999}
2000impl<'a> IterableProtoinfoSctpAttrs<'a> {
2001 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2002 Self {
2003 buf,
2004 pos: 0,
2005 orig_loc,
2006 }
2007 }
2008 pub fn get_buf(&self) -> &'a [u8] {
2009 self.buf
2010 }
2011}
2012impl<'a> Iterator for IterableProtoinfoSctpAttrs<'a> {
2013 type Item = Result<ProtoinfoSctpAttrs, ErrorContext>;
2014 fn next(&mut self) -> Option<Self::Item> {
2015 let mut pos;
2016 let mut r#type;
2017 loop {
2018 pos = self.pos;
2019 r#type = None;
2020 if self.buf.len() == self.pos {
2021 return None;
2022 }
2023 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2024 self.pos = self.buf.len();
2025 break;
2026 };
2027 r#type = Some(header.r#type);
2028 let res = match header.r#type {
2029 1u16 => ProtoinfoSctpAttrs::SctpState({
2030 let res = parse_u8(next);
2031 let Some(val) = res else { break };
2032 val
2033 }),
2034 2u16 => ProtoinfoSctpAttrs::VtagOriginal({
2035 let res = parse_be_u32(next);
2036 let Some(val) = res else { break };
2037 val
2038 }),
2039 3u16 => ProtoinfoSctpAttrs::VtagReply({
2040 let res = parse_be_u32(next);
2041 let Some(val) = res else { break };
2042 val
2043 }),
2044 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2045 n => continue,
2046 };
2047 return Some(Ok(res));
2048 }
2049 Some(Err(ErrorContext::new(
2050 "ProtoinfoSctpAttrs",
2051 r#type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
2052 self.orig_loc,
2053 self.buf.as_ptr().wrapping_add(pos) as usize,
2054 )))
2055 }
2056}
2057impl std::fmt::Debug for IterableProtoinfoSctpAttrs<'_> {
2058 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2059 let mut fmt = f.debug_struct("ProtoinfoSctpAttrs");
2060 for attr in self.clone() {
2061 let attr = match attr {
2062 Ok(a) => a,
2063 Err(err) => {
2064 fmt.finish()?;
2065 f.write_str("Err(")?;
2066 err.fmt(f)?;
2067 return f.write_str(")");
2068 }
2069 };
2070 match attr {
2071 ProtoinfoSctpAttrs::SctpState(val) => fmt.field(
2072 "SctpState",
2073 &FormatEnum(val.into(), NfCtSctpState::from_value),
2074 ),
2075 ProtoinfoSctpAttrs::VtagOriginal(val) => fmt.field("VtagOriginal", &val),
2076 ProtoinfoSctpAttrs::VtagReply(val) => fmt.field("VtagReply", &val),
2077 };
2078 }
2079 fmt.finish()
2080 }
2081}
2082impl IterableProtoinfoSctpAttrs<'_> {
2083 pub fn lookup_attr(
2084 &self,
2085 offset: usize,
2086 missing_type: Option<u16>,
2087 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2088 let mut stack = Vec::new();
2089 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2090 if missing_type.is_some() && cur == offset {
2091 stack.push(("ProtoinfoSctpAttrs", offset));
2092 return (
2093 stack,
2094 missing_type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
2095 );
2096 }
2097 if cur > offset || cur + self.buf.len() < offset {
2098 return (stack, None);
2099 }
2100 let mut attrs = self.clone();
2101 let mut last_off = cur + attrs.pos;
2102 while let Some(attr) = attrs.next() {
2103 let Ok(attr) = attr else { break };
2104 match attr {
2105 ProtoinfoSctpAttrs::SctpState(val) => {
2106 if last_off == offset {
2107 stack.push(("SctpState", last_off));
2108 break;
2109 }
2110 }
2111 ProtoinfoSctpAttrs::VtagOriginal(val) => {
2112 if last_off == offset {
2113 stack.push(("VtagOriginal", last_off));
2114 break;
2115 }
2116 }
2117 ProtoinfoSctpAttrs::VtagReply(val) => {
2118 if last_off == offset {
2119 stack.push(("VtagReply", last_off));
2120 break;
2121 }
2122 }
2123 _ => {}
2124 };
2125 last_off = cur + attrs.pos;
2126 }
2127 if !stack.is_empty() {
2128 stack.push(("ProtoinfoSctpAttrs", cur));
2129 }
2130 (stack, None)
2131 }
2132}
2133#[derive(Clone)]
2134pub enum ProtoinfoAttrs<'a> {
2135 #[doc = "conntrack tcp state information\n"]
2136 ProtoinfoTcp(IterableProtoinfoTcpAttrs<'a>),
2137 #[doc = "conntrack dccp state information\n"]
2138 ProtoinfoDccp(IterableProtoinfoDccpAttrs<'a>),
2139 #[doc = "conntrack sctp state information\n"]
2140 ProtoinfoSctp(IterableProtoinfoSctpAttrs<'a>),
2141}
2142impl<'a> IterableProtoinfoAttrs<'a> {
2143 #[doc = "conntrack tcp state information\n"]
2144 pub fn get_protoinfo_tcp(&self) -> Result<IterableProtoinfoTcpAttrs<'a>, ErrorContext> {
2145 let mut iter = self.clone();
2146 iter.pos = 0;
2147 for attr in iter {
2148 if let Ok(ProtoinfoAttrs::ProtoinfoTcp(val)) = attr {
2149 return Ok(val);
2150 }
2151 }
2152 Err(ErrorContext::new_missing(
2153 "ProtoinfoAttrs",
2154 "ProtoinfoTcp",
2155 self.orig_loc,
2156 self.buf.as_ptr() as usize,
2157 ))
2158 }
2159 #[doc = "conntrack dccp state information\n"]
2160 pub fn get_protoinfo_dccp(&self) -> Result<IterableProtoinfoDccpAttrs<'a>, ErrorContext> {
2161 let mut iter = self.clone();
2162 iter.pos = 0;
2163 for attr in iter {
2164 if let Ok(ProtoinfoAttrs::ProtoinfoDccp(val)) = attr {
2165 return Ok(val);
2166 }
2167 }
2168 Err(ErrorContext::new_missing(
2169 "ProtoinfoAttrs",
2170 "ProtoinfoDccp",
2171 self.orig_loc,
2172 self.buf.as_ptr() as usize,
2173 ))
2174 }
2175 #[doc = "conntrack sctp state information\n"]
2176 pub fn get_protoinfo_sctp(&self) -> Result<IterableProtoinfoSctpAttrs<'a>, ErrorContext> {
2177 let mut iter = self.clone();
2178 iter.pos = 0;
2179 for attr in iter {
2180 if let Ok(ProtoinfoAttrs::ProtoinfoSctp(val)) = attr {
2181 return Ok(val);
2182 }
2183 }
2184 Err(ErrorContext::new_missing(
2185 "ProtoinfoAttrs",
2186 "ProtoinfoSctp",
2187 self.orig_loc,
2188 self.buf.as_ptr() as usize,
2189 ))
2190 }
2191}
2192impl ProtoinfoAttrs<'_> {
2193 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoAttrs<'a> {
2194 IterableProtoinfoAttrs::with_loc(buf, buf.as_ptr() as usize)
2195 }
2196 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2197 let res = match r#type {
2198 1u16 => "ProtoinfoTcp",
2199 2u16 => "ProtoinfoDccp",
2200 3u16 => "ProtoinfoSctp",
2201 _ => return None,
2202 };
2203 Some(res)
2204 }
2205}
2206#[derive(Clone, Copy, Default)]
2207pub struct IterableProtoinfoAttrs<'a> {
2208 buf: &'a [u8],
2209 pos: usize,
2210 orig_loc: usize,
2211}
2212impl<'a> IterableProtoinfoAttrs<'a> {
2213 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2214 Self {
2215 buf,
2216 pos: 0,
2217 orig_loc,
2218 }
2219 }
2220 pub fn get_buf(&self) -> &'a [u8] {
2221 self.buf
2222 }
2223}
2224impl<'a> Iterator for IterableProtoinfoAttrs<'a> {
2225 type Item = Result<ProtoinfoAttrs<'a>, ErrorContext>;
2226 fn next(&mut self) -> Option<Self::Item> {
2227 let mut pos;
2228 let mut r#type;
2229 loop {
2230 pos = self.pos;
2231 r#type = None;
2232 if self.buf.len() == self.pos {
2233 return None;
2234 }
2235 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2236 self.pos = self.buf.len();
2237 break;
2238 };
2239 r#type = Some(header.r#type);
2240 let res = match header.r#type {
2241 1u16 => ProtoinfoAttrs::ProtoinfoTcp({
2242 let res = Some(IterableProtoinfoTcpAttrs::with_loc(next, self.orig_loc));
2243 let Some(val) = res else { break };
2244 val
2245 }),
2246 2u16 => ProtoinfoAttrs::ProtoinfoDccp({
2247 let res = Some(IterableProtoinfoDccpAttrs::with_loc(next, self.orig_loc));
2248 let Some(val) = res else { break };
2249 val
2250 }),
2251 3u16 => ProtoinfoAttrs::ProtoinfoSctp({
2252 let res = Some(IterableProtoinfoSctpAttrs::with_loc(next, self.orig_loc));
2253 let Some(val) = res else { break };
2254 val
2255 }),
2256 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2257 n => continue,
2258 };
2259 return Some(Ok(res));
2260 }
2261 Some(Err(ErrorContext::new(
2262 "ProtoinfoAttrs",
2263 r#type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2264 self.orig_loc,
2265 self.buf.as_ptr().wrapping_add(pos) as usize,
2266 )))
2267 }
2268}
2269impl<'a> std::fmt::Debug for IterableProtoinfoAttrs<'_> {
2270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2271 let mut fmt = f.debug_struct("ProtoinfoAttrs");
2272 for attr in self.clone() {
2273 let attr = match attr {
2274 Ok(a) => a,
2275 Err(err) => {
2276 fmt.finish()?;
2277 f.write_str("Err(")?;
2278 err.fmt(f)?;
2279 return f.write_str(")");
2280 }
2281 };
2282 match attr {
2283 ProtoinfoAttrs::ProtoinfoTcp(val) => fmt.field("ProtoinfoTcp", &val),
2284 ProtoinfoAttrs::ProtoinfoDccp(val) => fmt.field("ProtoinfoDccp", &val),
2285 ProtoinfoAttrs::ProtoinfoSctp(val) => fmt.field("ProtoinfoSctp", &val),
2286 };
2287 }
2288 fmt.finish()
2289 }
2290}
2291impl IterableProtoinfoAttrs<'_> {
2292 pub fn lookup_attr(
2293 &self,
2294 offset: usize,
2295 missing_type: Option<u16>,
2296 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2297 let mut stack = Vec::new();
2298 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2299 if missing_type.is_some() && cur == offset {
2300 stack.push(("ProtoinfoAttrs", offset));
2301 return (
2302 stack,
2303 missing_type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2304 );
2305 }
2306 if cur > offset || cur + self.buf.len() < offset {
2307 return (stack, None);
2308 }
2309 let mut attrs = self.clone();
2310 let mut last_off = cur + attrs.pos;
2311 let mut missing = None;
2312 while let Some(attr) = attrs.next() {
2313 let Ok(attr) = attr else { break };
2314 match attr {
2315 ProtoinfoAttrs::ProtoinfoTcp(val) => {
2316 (stack, missing) = val.lookup_attr(offset, missing_type);
2317 if !stack.is_empty() {
2318 break;
2319 }
2320 }
2321 ProtoinfoAttrs::ProtoinfoDccp(val) => {
2322 (stack, missing) = val.lookup_attr(offset, missing_type);
2323 if !stack.is_empty() {
2324 break;
2325 }
2326 }
2327 ProtoinfoAttrs::ProtoinfoSctp(val) => {
2328 (stack, missing) = val.lookup_attr(offset, missing_type);
2329 if !stack.is_empty() {
2330 break;
2331 }
2332 }
2333 _ => {}
2334 };
2335 last_off = cur + attrs.pos;
2336 }
2337 if !stack.is_empty() {
2338 stack.push(("ProtoinfoAttrs", cur));
2339 }
2340 (stack, missing)
2341 }
2342}
2343#[derive(Clone)]
2344pub enum HelpAttrs<'a> {
2345 #[doc = "helper name\n"]
2346 HelpName(&'a CStr),
2347}
2348impl<'a> IterableHelpAttrs<'a> {
2349 #[doc = "helper name\n"]
2350 pub fn get_help_name(&self) -> Result<&'a CStr, ErrorContext> {
2351 let mut iter = self.clone();
2352 iter.pos = 0;
2353 for attr in iter {
2354 if let Ok(HelpAttrs::HelpName(val)) = attr {
2355 return Ok(val);
2356 }
2357 }
2358 Err(ErrorContext::new_missing(
2359 "HelpAttrs",
2360 "HelpName",
2361 self.orig_loc,
2362 self.buf.as_ptr() as usize,
2363 ))
2364 }
2365}
2366impl HelpAttrs<'_> {
2367 pub fn new<'a>(buf: &'a [u8]) -> IterableHelpAttrs<'a> {
2368 IterableHelpAttrs::with_loc(buf, buf.as_ptr() as usize)
2369 }
2370 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2371 let res = match r#type {
2372 1u16 => "HelpName",
2373 _ => return None,
2374 };
2375 Some(res)
2376 }
2377}
2378#[derive(Clone, Copy, Default)]
2379pub struct IterableHelpAttrs<'a> {
2380 buf: &'a [u8],
2381 pos: usize,
2382 orig_loc: usize,
2383}
2384impl<'a> IterableHelpAttrs<'a> {
2385 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2386 Self {
2387 buf,
2388 pos: 0,
2389 orig_loc,
2390 }
2391 }
2392 pub fn get_buf(&self) -> &'a [u8] {
2393 self.buf
2394 }
2395}
2396impl<'a> Iterator for IterableHelpAttrs<'a> {
2397 type Item = Result<HelpAttrs<'a>, ErrorContext>;
2398 fn next(&mut self) -> Option<Self::Item> {
2399 let mut pos;
2400 let mut r#type;
2401 loop {
2402 pos = self.pos;
2403 r#type = None;
2404 if self.buf.len() == self.pos {
2405 return None;
2406 }
2407 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2408 self.pos = self.buf.len();
2409 break;
2410 };
2411 r#type = Some(header.r#type);
2412 let res = match header.r#type {
2413 1u16 => HelpAttrs::HelpName({
2414 let res = CStr::from_bytes_with_nul(next).ok();
2415 let Some(val) = res else { break };
2416 val
2417 }),
2418 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2419 n => continue,
2420 };
2421 return Some(Ok(res));
2422 }
2423 Some(Err(ErrorContext::new(
2424 "HelpAttrs",
2425 r#type.and_then(|t| HelpAttrs::attr_from_type(t)),
2426 self.orig_loc,
2427 self.buf.as_ptr().wrapping_add(pos) as usize,
2428 )))
2429 }
2430}
2431impl<'a> std::fmt::Debug for IterableHelpAttrs<'_> {
2432 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2433 let mut fmt = f.debug_struct("HelpAttrs");
2434 for attr in self.clone() {
2435 let attr = match attr {
2436 Ok(a) => a,
2437 Err(err) => {
2438 fmt.finish()?;
2439 f.write_str("Err(")?;
2440 err.fmt(f)?;
2441 return f.write_str(")");
2442 }
2443 };
2444 match attr {
2445 HelpAttrs::HelpName(val) => fmt.field("HelpName", &val),
2446 };
2447 }
2448 fmt.finish()
2449 }
2450}
2451impl IterableHelpAttrs<'_> {
2452 pub fn lookup_attr(
2453 &self,
2454 offset: usize,
2455 missing_type: Option<u16>,
2456 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2457 let mut stack = Vec::new();
2458 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2459 if missing_type.is_some() && cur == offset {
2460 stack.push(("HelpAttrs", offset));
2461 return (
2462 stack,
2463 missing_type.and_then(|t| HelpAttrs::attr_from_type(t)),
2464 );
2465 }
2466 if cur > offset || cur + self.buf.len() < offset {
2467 return (stack, None);
2468 }
2469 let mut attrs = self.clone();
2470 let mut last_off = cur + attrs.pos;
2471 while let Some(attr) = attrs.next() {
2472 let Ok(attr) = attr else { break };
2473 match attr {
2474 HelpAttrs::HelpName(val) => {
2475 if last_off == offset {
2476 stack.push(("HelpName", last_off));
2477 break;
2478 }
2479 }
2480 _ => {}
2481 };
2482 last_off = cur + attrs.pos;
2483 }
2484 if !stack.is_empty() {
2485 stack.push(("HelpAttrs", cur));
2486 }
2487 (stack, None)
2488 }
2489}
2490#[derive(Clone)]
2491pub enum NatProtoAttrs {
2492 NatPortMin(u16),
2493 NatPortMax(u16),
2494}
2495impl<'a> IterableNatProtoAttrs<'a> {
2496 pub fn get_nat_port_min(&self) -> Result<u16, ErrorContext> {
2497 let mut iter = self.clone();
2498 iter.pos = 0;
2499 for attr in iter {
2500 if let Ok(NatProtoAttrs::NatPortMin(val)) = attr {
2501 return Ok(val);
2502 }
2503 }
2504 Err(ErrorContext::new_missing(
2505 "NatProtoAttrs",
2506 "NatPortMin",
2507 self.orig_loc,
2508 self.buf.as_ptr() as usize,
2509 ))
2510 }
2511 pub fn get_nat_port_max(&self) -> Result<u16, ErrorContext> {
2512 let mut iter = self.clone();
2513 iter.pos = 0;
2514 for attr in iter {
2515 if let Ok(NatProtoAttrs::NatPortMax(val)) = attr {
2516 return Ok(val);
2517 }
2518 }
2519 Err(ErrorContext::new_missing(
2520 "NatProtoAttrs",
2521 "NatPortMax",
2522 self.orig_loc,
2523 self.buf.as_ptr() as usize,
2524 ))
2525 }
2526}
2527impl NatProtoAttrs {
2528 pub fn new<'a>(buf: &'a [u8]) -> IterableNatProtoAttrs<'a> {
2529 IterableNatProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
2530 }
2531 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2532 let res = match r#type {
2533 1u16 => "NatPortMin",
2534 2u16 => "NatPortMax",
2535 _ => return None,
2536 };
2537 Some(res)
2538 }
2539}
2540#[derive(Clone, Copy, Default)]
2541pub struct IterableNatProtoAttrs<'a> {
2542 buf: &'a [u8],
2543 pos: usize,
2544 orig_loc: usize,
2545}
2546impl<'a> IterableNatProtoAttrs<'a> {
2547 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2548 Self {
2549 buf,
2550 pos: 0,
2551 orig_loc,
2552 }
2553 }
2554 pub fn get_buf(&self) -> &'a [u8] {
2555 self.buf
2556 }
2557}
2558impl<'a> Iterator for IterableNatProtoAttrs<'a> {
2559 type Item = Result<NatProtoAttrs, ErrorContext>;
2560 fn next(&mut self) -> Option<Self::Item> {
2561 let mut pos;
2562 let mut r#type;
2563 loop {
2564 pos = self.pos;
2565 r#type = None;
2566 if self.buf.len() == self.pos {
2567 return None;
2568 }
2569 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2570 self.pos = self.buf.len();
2571 break;
2572 };
2573 r#type = Some(header.r#type);
2574 let res = match header.r#type {
2575 1u16 => NatProtoAttrs::NatPortMin({
2576 let res = parse_be_u16(next);
2577 let Some(val) = res else { break };
2578 val
2579 }),
2580 2u16 => NatProtoAttrs::NatPortMax({
2581 let res = parse_be_u16(next);
2582 let Some(val) = res else { break };
2583 val
2584 }),
2585 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2586 n => continue,
2587 };
2588 return Some(Ok(res));
2589 }
2590 Some(Err(ErrorContext::new(
2591 "NatProtoAttrs",
2592 r#type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2593 self.orig_loc,
2594 self.buf.as_ptr().wrapping_add(pos) as usize,
2595 )))
2596 }
2597}
2598impl std::fmt::Debug for IterableNatProtoAttrs<'_> {
2599 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2600 let mut fmt = f.debug_struct("NatProtoAttrs");
2601 for attr in self.clone() {
2602 let attr = match attr {
2603 Ok(a) => a,
2604 Err(err) => {
2605 fmt.finish()?;
2606 f.write_str("Err(")?;
2607 err.fmt(f)?;
2608 return f.write_str(")");
2609 }
2610 };
2611 match attr {
2612 NatProtoAttrs::NatPortMin(val) => fmt.field("NatPortMin", &val),
2613 NatProtoAttrs::NatPortMax(val) => fmt.field("NatPortMax", &val),
2614 };
2615 }
2616 fmt.finish()
2617 }
2618}
2619impl IterableNatProtoAttrs<'_> {
2620 pub fn lookup_attr(
2621 &self,
2622 offset: usize,
2623 missing_type: Option<u16>,
2624 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2625 let mut stack = Vec::new();
2626 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2627 if missing_type.is_some() && cur == offset {
2628 stack.push(("NatProtoAttrs", offset));
2629 return (
2630 stack,
2631 missing_type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2632 );
2633 }
2634 if cur > offset || cur + self.buf.len() < offset {
2635 return (stack, None);
2636 }
2637 let mut attrs = self.clone();
2638 let mut last_off = cur + attrs.pos;
2639 while let Some(attr) = attrs.next() {
2640 let Ok(attr) = attr else { break };
2641 match attr {
2642 NatProtoAttrs::NatPortMin(val) => {
2643 if last_off == offset {
2644 stack.push(("NatPortMin", last_off));
2645 break;
2646 }
2647 }
2648 NatProtoAttrs::NatPortMax(val) => {
2649 if last_off == offset {
2650 stack.push(("NatPortMax", last_off));
2651 break;
2652 }
2653 }
2654 _ => {}
2655 };
2656 last_off = cur + attrs.pos;
2657 }
2658 if !stack.is_empty() {
2659 stack.push(("NatProtoAttrs", cur));
2660 }
2661 (stack, None)
2662 }
2663}
2664#[derive(Clone)]
2665pub enum NatAttrs<'a> {
2666 NatV4Minip(u32),
2667 NatV4Maxip(u32),
2668 NatV6Minip(&'a [u8]),
2669 NatV6Maxip(&'a [u8]),
2670 NatProto(IterableNatProtoAttrs<'a>),
2671}
2672impl<'a> IterableNatAttrs<'a> {
2673 pub fn get_nat_v4_minip(&self) -> Result<u32, ErrorContext> {
2674 let mut iter = self.clone();
2675 iter.pos = 0;
2676 for attr in iter {
2677 if let Ok(NatAttrs::NatV4Minip(val)) = attr {
2678 return Ok(val);
2679 }
2680 }
2681 Err(ErrorContext::new_missing(
2682 "NatAttrs",
2683 "NatV4Minip",
2684 self.orig_loc,
2685 self.buf.as_ptr() as usize,
2686 ))
2687 }
2688 pub fn get_nat_v4_maxip(&self) -> Result<u32, ErrorContext> {
2689 let mut iter = self.clone();
2690 iter.pos = 0;
2691 for attr in iter {
2692 if let Ok(NatAttrs::NatV4Maxip(val)) = attr {
2693 return Ok(val);
2694 }
2695 }
2696 Err(ErrorContext::new_missing(
2697 "NatAttrs",
2698 "NatV4Maxip",
2699 self.orig_loc,
2700 self.buf.as_ptr() as usize,
2701 ))
2702 }
2703 pub fn get_nat_v6_minip(&self) -> Result<&'a [u8], ErrorContext> {
2704 let mut iter = self.clone();
2705 iter.pos = 0;
2706 for attr in iter {
2707 if let Ok(NatAttrs::NatV6Minip(val)) = attr {
2708 return Ok(val);
2709 }
2710 }
2711 Err(ErrorContext::new_missing(
2712 "NatAttrs",
2713 "NatV6Minip",
2714 self.orig_loc,
2715 self.buf.as_ptr() as usize,
2716 ))
2717 }
2718 pub fn get_nat_v6_maxip(&self) -> Result<&'a [u8], ErrorContext> {
2719 let mut iter = self.clone();
2720 iter.pos = 0;
2721 for attr in iter {
2722 if let Ok(NatAttrs::NatV6Maxip(val)) = attr {
2723 return Ok(val);
2724 }
2725 }
2726 Err(ErrorContext::new_missing(
2727 "NatAttrs",
2728 "NatV6Maxip",
2729 self.orig_loc,
2730 self.buf.as_ptr() as usize,
2731 ))
2732 }
2733 pub fn get_nat_proto(&self) -> Result<IterableNatProtoAttrs<'a>, ErrorContext> {
2734 let mut iter = self.clone();
2735 iter.pos = 0;
2736 for attr in iter {
2737 if let Ok(NatAttrs::NatProto(val)) = attr {
2738 return Ok(val);
2739 }
2740 }
2741 Err(ErrorContext::new_missing(
2742 "NatAttrs",
2743 "NatProto",
2744 self.orig_loc,
2745 self.buf.as_ptr() as usize,
2746 ))
2747 }
2748}
2749impl NatAttrs<'_> {
2750 pub fn new<'a>(buf: &'a [u8]) -> IterableNatAttrs<'a> {
2751 IterableNatAttrs::with_loc(buf, buf.as_ptr() as usize)
2752 }
2753 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2754 let res = match r#type {
2755 1u16 => "NatV4Minip",
2756 2u16 => "NatV4Maxip",
2757 3u16 => "NatV6Minip",
2758 4u16 => "NatV6Maxip",
2759 5u16 => "NatProto",
2760 _ => return None,
2761 };
2762 Some(res)
2763 }
2764}
2765#[derive(Clone, Copy, Default)]
2766pub struct IterableNatAttrs<'a> {
2767 buf: &'a [u8],
2768 pos: usize,
2769 orig_loc: usize,
2770}
2771impl<'a> IterableNatAttrs<'a> {
2772 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2773 Self {
2774 buf,
2775 pos: 0,
2776 orig_loc,
2777 }
2778 }
2779 pub fn get_buf(&self) -> &'a [u8] {
2780 self.buf
2781 }
2782}
2783impl<'a> Iterator for IterableNatAttrs<'a> {
2784 type Item = Result<NatAttrs<'a>, ErrorContext>;
2785 fn next(&mut self) -> Option<Self::Item> {
2786 let mut pos;
2787 let mut r#type;
2788 loop {
2789 pos = self.pos;
2790 r#type = None;
2791 if self.buf.len() == self.pos {
2792 return None;
2793 }
2794 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2795 self.pos = self.buf.len();
2796 break;
2797 };
2798 r#type = Some(header.r#type);
2799 let res = match header.r#type {
2800 1u16 => NatAttrs::NatV4Minip({
2801 let res = parse_be_u32(next);
2802 let Some(val) = res else { break };
2803 val
2804 }),
2805 2u16 => NatAttrs::NatV4Maxip({
2806 let res = parse_be_u32(next);
2807 let Some(val) = res else { break };
2808 val
2809 }),
2810 3u16 => NatAttrs::NatV6Minip({
2811 let res = Some(next);
2812 let Some(val) = res else { break };
2813 val
2814 }),
2815 4u16 => NatAttrs::NatV6Maxip({
2816 let res = Some(next);
2817 let Some(val) = res else { break };
2818 val
2819 }),
2820 5u16 => NatAttrs::NatProto({
2821 let res = Some(IterableNatProtoAttrs::with_loc(next, self.orig_loc));
2822 let Some(val) = res else { break };
2823 val
2824 }),
2825 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2826 n => continue,
2827 };
2828 return Some(Ok(res));
2829 }
2830 Some(Err(ErrorContext::new(
2831 "NatAttrs",
2832 r#type.and_then(|t| NatAttrs::attr_from_type(t)),
2833 self.orig_loc,
2834 self.buf.as_ptr().wrapping_add(pos) as usize,
2835 )))
2836 }
2837}
2838impl<'a> std::fmt::Debug for IterableNatAttrs<'_> {
2839 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2840 let mut fmt = f.debug_struct("NatAttrs");
2841 for attr in self.clone() {
2842 let attr = match attr {
2843 Ok(a) => a,
2844 Err(err) => {
2845 fmt.finish()?;
2846 f.write_str("Err(")?;
2847 err.fmt(f)?;
2848 return f.write_str(")");
2849 }
2850 };
2851 match attr {
2852 NatAttrs::NatV4Minip(val) => fmt.field("NatV4Minip", &val),
2853 NatAttrs::NatV4Maxip(val) => fmt.field("NatV4Maxip", &val),
2854 NatAttrs::NatV6Minip(val) => fmt.field("NatV6Minip", &val),
2855 NatAttrs::NatV6Maxip(val) => fmt.field("NatV6Maxip", &val),
2856 NatAttrs::NatProto(val) => fmt.field("NatProto", &val),
2857 };
2858 }
2859 fmt.finish()
2860 }
2861}
2862impl IterableNatAttrs<'_> {
2863 pub fn lookup_attr(
2864 &self,
2865 offset: usize,
2866 missing_type: Option<u16>,
2867 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2868 let mut stack = Vec::new();
2869 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2870 if missing_type.is_some() && cur == offset {
2871 stack.push(("NatAttrs", offset));
2872 return (
2873 stack,
2874 missing_type.and_then(|t| NatAttrs::attr_from_type(t)),
2875 );
2876 }
2877 if cur > offset || cur + self.buf.len() < offset {
2878 return (stack, None);
2879 }
2880 let mut attrs = self.clone();
2881 let mut last_off = cur + attrs.pos;
2882 let mut missing = None;
2883 while let Some(attr) = attrs.next() {
2884 let Ok(attr) = attr else { break };
2885 match attr {
2886 NatAttrs::NatV4Minip(val) => {
2887 if last_off == offset {
2888 stack.push(("NatV4Minip", last_off));
2889 break;
2890 }
2891 }
2892 NatAttrs::NatV4Maxip(val) => {
2893 if last_off == offset {
2894 stack.push(("NatV4Maxip", last_off));
2895 break;
2896 }
2897 }
2898 NatAttrs::NatV6Minip(val) => {
2899 if last_off == offset {
2900 stack.push(("NatV6Minip", last_off));
2901 break;
2902 }
2903 }
2904 NatAttrs::NatV6Maxip(val) => {
2905 if last_off == offset {
2906 stack.push(("NatV6Maxip", last_off));
2907 break;
2908 }
2909 }
2910 NatAttrs::NatProto(val) => {
2911 (stack, missing) = val.lookup_attr(offset, missing_type);
2912 if !stack.is_empty() {
2913 break;
2914 }
2915 }
2916 _ => {}
2917 };
2918 last_off = cur + attrs.pos;
2919 }
2920 if !stack.is_empty() {
2921 stack.push(("NatAttrs", cur));
2922 }
2923 (stack, missing)
2924 }
2925}
2926#[derive(Clone)]
2927pub enum SeqadjAttrs {
2928 CorrectionPos(u32),
2929 OffsetBefore(u32),
2930 OffsetAfter(u32),
2931}
2932impl<'a> IterableSeqadjAttrs<'a> {
2933 pub fn get_correction_pos(&self) -> Result<u32, ErrorContext> {
2934 let mut iter = self.clone();
2935 iter.pos = 0;
2936 for attr in iter {
2937 if let Ok(SeqadjAttrs::CorrectionPos(val)) = attr {
2938 return Ok(val);
2939 }
2940 }
2941 Err(ErrorContext::new_missing(
2942 "SeqadjAttrs",
2943 "CorrectionPos",
2944 self.orig_loc,
2945 self.buf.as_ptr() as usize,
2946 ))
2947 }
2948 pub fn get_offset_before(&self) -> Result<u32, ErrorContext> {
2949 let mut iter = self.clone();
2950 iter.pos = 0;
2951 for attr in iter {
2952 if let Ok(SeqadjAttrs::OffsetBefore(val)) = attr {
2953 return Ok(val);
2954 }
2955 }
2956 Err(ErrorContext::new_missing(
2957 "SeqadjAttrs",
2958 "OffsetBefore",
2959 self.orig_loc,
2960 self.buf.as_ptr() as usize,
2961 ))
2962 }
2963 pub fn get_offset_after(&self) -> Result<u32, ErrorContext> {
2964 let mut iter = self.clone();
2965 iter.pos = 0;
2966 for attr in iter {
2967 if let Ok(SeqadjAttrs::OffsetAfter(val)) = attr {
2968 return Ok(val);
2969 }
2970 }
2971 Err(ErrorContext::new_missing(
2972 "SeqadjAttrs",
2973 "OffsetAfter",
2974 self.orig_loc,
2975 self.buf.as_ptr() as usize,
2976 ))
2977 }
2978}
2979impl SeqadjAttrs {
2980 pub fn new<'a>(buf: &'a [u8]) -> IterableSeqadjAttrs<'a> {
2981 IterableSeqadjAttrs::with_loc(buf, buf.as_ptr() as usize)
2982 }
2983 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2984 let res = match r#type {
2985 1u16 => "CorrectionPos",
2986 2u16 => "OffsetBefore",
2987 3u16 => "OffsetAfter",
2988 _ => return None,
2989 };
2990 Some(res)
2991 }
2992}
2993#[derive(Clone, Copy, Default)]
2994pub struct IterableSeqadjAttrs<'a> {
2995 buf: &'a [u8],
2996 pos: usize,
2997 orig_loc: usize,
2998}
2999impl<'a> IterableSeqadjAttrs<'a> {
3000 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3001 Self {
3002 buf,
3003 pos: 0,
3004 orig_loc,
3005 }
3006 }
3007 pub fn get_buf(&self) -> &'a [u8] {
3008 self.buf
3009 }
3010}
3011impl<'a> Iterator for IterableSeqadjAttrs<'a> {
3012 type Item = Result<SeqadjAttrs, ErrorContext>;
3013 fn next(&mut self) -> Option<Self::Item> {
3014 let mut pos;
3015 let mut r#type;
3016 loop {
3017 pos = self.pos;
3018 r#type = None;
3019 if self.buf.len() == self.pos {
3020 return None;
3021 }
3022 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3023 self.pos = self.buf.len();
3024 break;
3025 };
3026 r#type = Some(header.r#type);
3027 let res = match header.r#type {
3028 1u16 => SeqadjAttrs::CorrectionPos({
3029 let res = parse_be_u32(next);
3030 let Some(val) = res else { break };
3031 val
3032 }),
3033 2u16 => SeqadjAttrs::OffsetBefore({
3034 let res = parse_be_u32(next);
3035 let Some(val) = res else { break };
3036 val
3037 }),
3038 3u16 => SeqadjAttrs::OffsetAfter({
3039 let res = parse_be_u32(next);
3040 let Some(val) = res else { break };
3041 val
3042 }),
3043 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3044 n => continue,
3045 };
3046 return Some(Ok(res));
3047 }
3048 Some(Err(ErrorContext::new(
3049 "SeqadjAttrs",
3050 r#type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
3051 self.orig_loc,
3052 self.buf.as_ptr().wrapping_add(pos) as usize,
3053 )))
3054 }
3055}
3056impl std::fmt::Debug for IterableSeqadjAttrs<'_> {
3057 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3058 let mut fmt = f.debug_struct("SeqadjAttrs");
3059 for attr in self.clone() {
3060 let attr = match attr {
3061 Ok(a) => a,
3062 Err(err) => {
3063 fmt.finish()?;
3064 f.write_str("Err(")?;
3065 err.fmt(f)?;
3066 return f.write_str(")");
3067 }
3068 };
3069 match attr {
3070 SeqadjAttrs::CorrectionPos(val) => fmt.field("CorrectionPos", &val),
3071 SeqadjAttrs::OffsetBefore(val) => fmt.field("OffsetBefore", &val),
3072 SeqadjAttrs::OffsetAfter(val) => fmt.field("OffsetAfter", &val),
3073 };
3074 }
3075 fmt.finish()
3076 }
3077}
3078impl IterableSeqadjAttrs<'_> {
3079 pub fn lookup_attr(
3080 &self,
3081 offset: usize,
3082 missing_type: Option<u16>,
3083 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3084 let mut stack = Vec::new();
3085 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3086 if missing_type.is_some() && cur == offset {
3087 stack.push(("SeqadjAttrs", offset));
3088 return (
3089 stack,
3090 missing_type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
3091 );
3092 }
3093 if cur > offset || cur + self.buf.len() < offset {
3094 return (stack, None);
3095 }
3096 let mut attrs = self.clone();
3097 let mut last_off = cur + attrs.pos;
3098 while let Some(attr) = attrs.next() {
3099 let Ok(attr) = attr else { break };
3100 match attr {
3101 SeqadjAttrs::CorrectionPos(val) => {
3102 if last_off == offset {
3103 stack.push(("CorrectionPos", last_off));
3104 break;
3105 }
3106 }
3107 SeqadjAttrs::OffsetBefore(val) => {
3108 if last_off == offset {
3109 stack.push(("OffsetBefore", last_off));
3110 break;
3111 }
3112 }
3113 SeqadjAttrs::OffsetAfter(val) => {
3114 if last_off == offset {
3115 stack.push(("OffsetAfter", last_off));
3116 break;
3117 }
3118 }
3119 _ => {}
3120 };
3121 last_off = cur + attrs.pos;
3122 }
3123 if !stack.is_empty() {
3124 stack.push(("SeqadjAttrs", cur));
3125 }
3126 (stack, None)
3127 }
3128}
3129#[derive(Clone)]
3130pub enum SecctxAttrs<'a> {
3131 SecctxName(&'a CStr),
3132}
3133impl<'a> IterableSecctxAttrs<'a> {
3134 pub fn get_secctx_name(&self) -> Result<&'a CStr, ErrorContext> {
3135 let mut iter = self.clone();
3136 iter.pos = 0;
3137 for attr in iter {
3138 if let Ok(SecctxAttrs::SecctxName(val)) = attr {
3139 return Ok(val);
3140 }
3141 }
3142 Err(ErrorContext::new_missing(
3143 "SecctxAttrs",
3144 "SecctxName",
3145 self.orig_loc,
3146 self.buf.as_ptr() as usize,
3147 ))
3148 }
3149}
3150impl SecctxAttrs<'_> {
3151 pub fn new<'a>(buf: &'a [u8]) -> IterableSecctxAttrs<'a> {
3152 IterableSecctxAttrs::with_loc(buf, buf.as_ptr() as usize)
3153 }
3154 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3155 let res = match r#type {
3156 1u16 => "SecctxName",
3157 _ => return None,
3158 };
3159 Some(res)
3160 }
3161}
3162#[derive(Clone, Copy, Default)]
3163pub struct IterableSecctxAttrs<'a> {
3164 buf: &'a [u8],
3165 pos: usize,
3166 orig_loc: usize,
3167}
3168impl<'a> IterableSecctxAttrs<'a> {
3169 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3170 Self {
3171 buf,
3172 pos: 0,
3173 orig_loc,
3174 }
3175 }
3176 pub fn get_buf(&self) -> &'a [u8] {
3177 self.buf
3178 }
3179}
3180impl<'a> Iterator for IterableSecctxAttrs<'a> {
3181 type Item = Result<SecctxAttrs<'a>, ErrorContext>;
3182 fn next(&mut self) -> Option<Self::Item> {
3183 let mut pos;
3184 let mut r#type;
3185 loop {
3186 pos = self.pos;
3187 r#type = None;
3188 if self.buf.len() == self.pos {
3189 return None;
3190 }
3191 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3192 self.pos = self.buf.len();
3193 break;
3194 };
3195 r#type = Some(header.r#type);
3196 let res = match header.r#type {
3197 1u16 => SecctxAttrs::SecctxName({
3198 let res = CStr::from_bytes_with_nul(next).ok();
3199 let Some(val) = res else { break };
3200 val
3201 }),
3202 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3203 n => continue,
3204 };
3205 return Some(Ok(res));
3206 }
3207 Some(Err(ErrorContext::new(
3208 "SecctxAttrs",
3209 r#type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3210 self.orig_loc,
3211 self.buf.as_ptr().wrapping_add(pos) as usize,
3212 )))
3213 }
3214}
3215impl<'a> std::fmt::Debug for IterableSecctxAttrs<'_> {
3216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3217 let mut fmt = f.debug_struct("SecctxAttrs");
3218 for attr in self.clone() {
3219 let attr = match attr {
3220 Ok(a) => a,
3221 Err(err) => {
3222 fmt.finish()?;
3223 f.write_str("Err(")?;
3224 err.fmt(f)?;
3225 return f.write_str(")");
3226 }
3227 };
3228 match attr {
3229 SecctxAttrs::SecctxName(val) => fmt.field("SecctxName", &val),
3230 };
3231 }
3232 fmt.finish()
3233 }
3234}
3235impl IterableSecctxAttrs<'_> {
3236 pub fn lookup_attr(
3237 &self,
3238 offset: usize,
3239 missing_type: Option<u16>,
3240 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3241 let mut stack = Vec::new();
3242 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3243 if missing_type.is_some() && cur == offset {
3244 stack.push(("SecctxAttrs", offset));
3245 return (
3246 stack,
3247 missing_type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3248 );
3249 }
3250 if cur > offset || cur + self.buf.len() < offset {
3251 return (stack, None);
3252 }
3253 let mut attrs = self.clone();
3254 let mut last_off = cur + attrs.pos;
3255 while let Some(attr) = attrs.next() {
3256 let Ok(attr) = attr else { break };
3257 match attr {
3258 SecctxAttrs::SecctxName(val) => {
3259 if last_off == offset {
3260 stack.push(("SecctxName", last_off));
3261 break;
3262 }
3263 }
3264 _ => {}
3265 };
3266 last_off = cur + attrs.pos;
3267 }
3268 if !stack.is_empty() {
3269 stack.push(("SecctxAttrs", cur));
3270 }
3271 (stack, None)
3272 }
3273}
3274#[derive(Clone)]
3275pub enum SynproxyAttrs {
3276 Isn(u32),
3277 Its(u32),
3278 Tsoff(u32),
3279}
3280impl<'a> IterableSynproxyAttrs<'a> {
3281 pub fn get_isn(&self) -> Result<u32, ErrorContext> {
3282 let mut iter = self.clone();
3283 iter.pos = 0;
3284 for attr in iter {
3285 if let Ok(SynproxyAttrs::Isn(val)) = attr {
3286 return Ok(val);
3287 }
3288 }
3289 Err(ErrorContext::new_missing(
3290 "SynproxyAttrs",
3291 "Isn",
3292 self.orig_loc,
3293 self.buf.as_ptr() as usize,
3294 ))
3295 }
3296 pub fn get_its(&self) -> Result<u32, ErrorContext> {
3297 let mut iter = self.clone();
3298 iter.pos = 0;
3299 for attr in iter {
3300 if let Ok(SynproxyAttrs::Its(val)) = attr {
3301 return Ok(val);
3302 }
3303 }
3304 Err(ErrorContext::new_missing(
3305 "SynproxyAttrs",
3306 "Its",
3307 self.orig_loc,
3308 self.buf.as_ptr() as usize,
3309 ))
3310 }
3311 pub fn get_tsoff(&self) -> Result<u32, ErrorContext> {
3312 let mut iter = self.clone();
3313 iter.pos = 0;
3314 for attr in iter {
3315 if let Ok(SynproxyAttrs::Tsoff(val)) = attr {
3316 return Ok(val);
3317 }
3318 }
3319 Err(ErrorContext::new_missing(
3320 "SynproxyAttrs",
3321 "Tsoff",
3322 self.orig_loc,
3323 self.buf.as_ptr() as usize,
3324 ))
3325 }
3326}
3327impl SynproxyAttrs {
3328 pub fn new<'a>(buf: &'a [u8]) -> IterableSynproxyAttrs<'a> {
3329 IterableSynproxyAttrs::with_loc(buf, buf.as_ptr() as usize)
3330 }
3331 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3332 let res = match r#type {
3333 1u16 => "Isn",
3334 2u16 => "Its",
3335 3u16 => "Tsoff",
3336 _ => return None,
3337 };
3338 Some(res)
3339 }
3340}
3341#[derive(Clone, Copy, Default)]
3342pub struct IterableSynproxyAttrs<'a> {
3343 buf: &'a [u8],
3344 pos: usize,
3345 orig_loc: usize,
3346}
3347impl<'a> IterableSynproxyAttrs<'a> {
3348 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3349 Self {
3350 buf,
3351 pos: 0,
3352 orig_loc,
3353 }
3354 }
3355 pub fn get_buf(&self) -> &'a [u8] {
3356 self.buf
3357 }
3358}
3359impl<'a> Iterator for IterableSynproxyAttrs<'a> {
3360 type Item = Result<SynproxyAttrs, ErrorContext>;
3361 fn next(&mut self) -> Option<Self::Item> {
3362 let mut pos;
3363 let mut r#type;
3364 loop {
3365 pos = self.pos;
3366 r#type = None;
3367 if self.buf.len() == self.pos {
3368 return None;
3369 }
3370 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3371 self.pos = self.buf.len();
3372 break;
3373 };
3374 r#type = Some(header.r#type);
3375 let res = match header.r#type {
3376 1u16 => SynproxyAttrs::Isn({
3377 let res = parse_be_u32(next);
3378 let Some(val) = res else { break };
3379 val
3380 }),
3381 2u16 => SynproxyAttrs::Its({
3382 let res = parse_be_u32(next);
3383 let Some(val) = res else { break };
3384 val
3385 }),
3386 3u16 => SynproxyAttrs::Tsoff({
3387 let res = parse_be_u32(next);
3388 let Some(val) = res else { break };
3389 val
3390 }),
3391 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3392 n => continue,
3393 };
3394 return Some(Ok(res));
3395 }
3396 Some(Err(ErrorContext::new(
3397 "SynproxyAttrs",
3398 r#type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3399 self.orig_loc,
3400 self.buf.as_ptr().wrapping_add(pos) as usize,
3401 )))
3402 }
3403}
3404impl std::fmt::Debug for IterableSynproxyAttrs<'_> {
3405 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3406 let mut fmt = f.debug_struct("SynproxyAttrs");
3407 for attr in self.clone() {
3408 let attr = match attr {
3409 Ok(a) => a,
3410 Err(err) => {
3411 fmt.finish()?;
3412 f.write_str("Err(")?;
3413 err.fmt(f)?;
3414 return f.write_str(")");
3415 }
3416 };
3417 match attr {
3418 SynproxyAttrs::Isn(val) => fmt.field("Isn", &val),
3419 SynproxyAttrs::Its(val) => fmt.field("Its", &val),
3420 SynproxyAttrs::Tsoff(val) => fmt.field("Tsoff", &val),
3421 };
3422 }
3423 fmt.finish()
3424 }
3425}
3426impl IterableSynproxyAttrs<'_> {
3427 pub fn lookup_attr(
3428 &self,
3429 offset: usize,
3430 missing_type: Option<u16>,
3431 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3432 let mut stack = Vec::new();
3433 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3434 if missing_type.is_some() && cur == offset {
3435 stack.push(("SynproxyAttrs", offset));
3436 return (
3437 stack,
3438 missing_type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3439 );
3440 }
3441 if cur > offset || cur + self.buf.len() < offset {
3442 return (stack, None);
3443 }
3444 let mut attrs = self.clone();
3445 let mut last_off = cur + attrs.pos;
3446 while let Some(attr) = attrs.next() {
3447 let Ok(attr) = attr else { break };
3448 match attr {
3449 SynproxyAttrs::Isn(val) => {
3450 if last_off == offset {
3451 stack.push(("Isn", last_off));
3452 break;
3453 }
3454 }
3455 SynproxyAttrs::Its(val) => {
3456 if last_off == offset {
3457 stack.push(("Its", last_off));
3458 break;
3459 }
3460 }
3461 SynproxyAttrs::Tsoff(val) => {
3462 if last_off == offset {
3463 stack.push(("Tsoff", last_off));
3464 break;
3465 }
3466 }
3467 _ => {}
3468 };
3469 last_off = cur + attrs.pos;
3470 }
3471 if !stack.is_empty() {
3472 stack.push(("SynproxyAttrs", cur));
3473 }
3474 (stack, None)
3475 }
3476}
3477#[derive(Clone)]
3478pub enum ConntrackAttrs<'a> {
3479 #[doc = "conntrack l3+l4 protocol information, original direction\n"]
3480 TupleOrig(IterableTupleAttrs<'a>),
3481 #[doc = "conntrack l3+l4 protocol information, reply direction\n"]
3482 TupleReply(IterableTupleAttrs<'a>),
3483 #[doc = "conntrack flag bits\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3484 Status(u32),
3485 Protoinfo(IterableProtoinfoAttrs<'a>),
3486 Help(IterableHelpAttrs<'a>),
3487 NatSrc(IterableNatAttrs<'a>),
3488 Timeout(u32),
3489 Mark(u32),
3490 CountersOrig(IterableCounterAttrs<'a>),
3491 CountersReply(IterableCounterAttrs<'a>),
3492 Use(u32),
3493 Id(u32),
3494 NatDst(IterableNatAttrs<'a>),
3495 TupleMaster(IterableTupleAttrs<'a>),
3496 SeqAdjOrig(IterableSeqadjAttrs<'a>),
3497 SeqAdjReply(IterableSeqadjAttrs<'a>),
3498 #[doc = "obsolete\n"]
3499 Secmark(&'a [u8]),
3500 #[doc = "conntrack zone id\n"]
3501 Zone(u16),
3502 Secctx(IterableSecctxAttrs<'a>),
3503 Timestamp(u64),
3504 MarkMask(u32),
3505 Labels(&'a [u8]),
3506 LabelsMask(&'a [u8]),
3507 Synproxy(IterableSynproxyAttrs<'a>),
3508 Filter(IterableTupleAttrs<'a>),
3509 #[doc = "conntrack flag bits to change\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3510 StatusMask(u32),
3511 TimestampEvent(u64),
3512}
3513impl<'a> IterableConntrackAttrs<'a> {
3514 #[doc = "conntrack l3+l4 protocol information, original direction\n"]
3515 pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3516 let mut iter = self.clone();
3517 iter.pos = 0;
3518 for attr in iter {
3519 if let Ok(ConntrackAttrs::TupleOrig(val)) = attr {
3520 return Ok(val);
3521 }
3522 }
3523 Err(ErrorContext::new_missing(
3524 "ConntrackAttrs",
3525 "TupleOrig",
3526 self.orig_loc,
3527 self.buf.as_ptr() as usize,
3528 ))
3529 }
3530 #[doc = "conntrack l3+l4 protocol information, reply direction\n"]
3531 pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3532 let mut iter = self.clone();
3533 iter.pos = 0;
3534 for attr in iter {
3535 if let Ok(ConntrackAttrs::TupleReply(val)) = attr {
3536 return Ok(val);
3537 }
3538 }
3539 Err(ErrorContext::new_missing(
3540 "ConntrackAttrs",
3541 "TupleReply",
3542 self.orig_loc,
3543 self.buf.as_ptr() as usize,
3544 ))
3545 }
3546 #[doc = "conntrack flag bits\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3547 pub fn get_status(&self) -> Result<u32, ErrorContext> {
3548 let mut iter = self.clone();
3549 iter.pos = 0;
3550 for attr in iter {
3551 if let Ok(ConntrackAttrs::Status(val)) = attr {
3552 return Ok(val);
3553 }
3554 }
3555 Err(ErrorContext::new_missing(
3556 "ConntrackAttrs",
3557 "Status",
3558 self.orig_loc,
3559 self.buf.as_ptr() as usize,
3560 ))
3561 }
3562 pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
3563 let mut iter = self.clone();
3564 iter.pos = 0;
3565 for attr in iter {
3566 if let Ok(ConntrackAttrs::Protoinfo(val)) = attr {
3567 return Ok(val);
3568 }
3569 }
3570 Err(ErrorContext::new_missing(
3571 "ConntrackAttrs",
3572 "Protoinfo",
3573 self.orig_loc,
3574 self.buf.as_ptr() as usize,
3575 ))
3576 }
3577 pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
3578 let mut iter = self.clone();
3579 iter.pos = 0;
3580 for attr in iter {
3581 if let Ok(ConntrackAttrs::Help(val)) = attr {
3582 return Ok(val);
3583 }
3584 }
3585 Err(ErrorContext::new_missing(
3586 "ConntrackAttrs",
3587 "Help",
3588 self.orig_loc,
3589 self.buf.as_ptr() as usize,
3590 ))
3591 }
3592 pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3593 let mut iter = self.clone();
3594 iter.pos = 0;
3595 for attr in iter {
3596 if let Ok(ConntrackAttrs::NatSrc(val)) = attr {
3597 return Ok(val);
3598 }
3599 }
3600 Err(ErrorContext::new_missing(
3601 "ConntrackAttrs",
3602 "NatSrc",
3603 self.orig_loc,
3604 self.buf.as_ptr() as usize,
3605 ))
3606 }
3607 pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
3608 let mut iter = self.clone();
3609 iter.pos = 0;
3610 for attr in iter {
3611 if let Ok(ConntrackAttrs::Timeout(val)) = attr {
3612 return Ok(val);
3613 }
3614 }
3615 Err(ErrorContext::new_missing(
3616 "ConntrackAttrs",
3617 "Timeout",
3618 self.orig_loc,
3619 self.buf.as_ptr() as usize,
3620 ))
3621 }
3622 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
3623 let mut iter = self.clone();
3624 iter.pos = 0;
3625 for attr in iter {
3626 if let Ok(ConntrackAttrs::Mark(val)) = attr {
3627 return Ok(val);
3628 }
3629 }
3630 Err(ErrorContext::new_missing(
3631 "ConntrackAttrs",
3632 "Mark",
3633 self.orig_loc,
3634 self.buf.as_ptr() as usize,
3635 ))
3636 }
3637 pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3638 let mut iter = self.clone();
3639 iter.pos = 0;
3640 for attr in iter {
3641 if let Ok(ConntrackAttrs::CountersOrig(val)) = attr {
3642 return Ok(val);
3643 }
3644 }
3645 Err(ErrorContext::new_missing(
3646 "ConntrackAttrs",
3647 "CountersOrig",
3648 self.orig_loc,
3649 self.buf.as_ptr() as usize,
3650 ))
3651 }
3652 pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3653 let mut iter = self.clone();
3654 iter.pos = 0;
3655 for attr in iter {
3656 if let Ok(ConntrackAttrs::CountersReply(val)) = attr {
3657 return Ok(val);
3658 }
3659 }
3660 Err(ErrorContext::new_missing(
3661 "ConntrackAttrs",
3662 "CountersReply",
3663 self.orig_loc,
3664 self.buf.as_ptr() as usize,
3665 ))
3666 }
3667 pub fn get_use(&self) -> Result<u32, ErrorContext> {
3668 let mut iter = self.clone();
3669 iter.pos = 0;
3670 for attr in iter {
3671 if let Ok(ConntrackAttrs::Use(val)) = attr {
3672 return Ok(val);
3673 }
3674 }
3675 Err(ErrorContext::new_missing(
3676 "ConntrackAttrs",
3677 "Use",
3678 self.orig_loc,
3679 self.buf.as_ptr() as usize,
3680 ))
3681 }
3682 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3683 let mut iter = self.clone();
3684 iter.pos = 0;
3685 for attr in iter {
3686 if let Ok(ConntrackAttrs::Id(val)) = attr {
3687 return Ok(val);
3688 }
3689 }
3690 Err(ErrorContext::new_missing(
3691 "ConntrackAttrs",
3692 "Id",
3693 self.orig_loc,
3694 self.buf.as_ptr() as usize,
3695 ))
3696 }
3697 pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3698 let mut iter = self.clone();
3699 iter.pos = 0;
3700 for attr in iter {
3701 if let Ok(ConntrackAttrs::NatDst(val)) = attr {
3702 return Ok(val);
3703 }
3704 }
3705 Err(ErrorContext::new_missing(
3706 "ConntrackAttrs",
3707 "NatDst",
3708 self.orig_loc,
3709 self.buf.as_ptr() as usize,
3710 ))
3711 }
3712 pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3713 let mut iter = self.clone();
3714 iter.pos = 0;
3715 for attr in iter {
3716 if let Ok(ConntrackAttrs::TupleMaster(val)) = attr {
3717 return Ok(val);
3718 }
3719 }
3720 Err(ErrorContext::new_missing(
3721 "ConntrackAttrs",
3722 "TupleMaster",
3723 self.orig_loc,
3724 self.buf.as_ptr() as usize,
3725 ))
3726 }
3727 pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3728 let mut iter = self.clone();
3729 iter.pos = 0;
3730 for attr in iter {
3731 if let Ok(ConntrackAttrs::SeqAdjOrig(val)) = attr {
3732 return Ok(val);
3733 }
3734 }
3735 Err(ErrorContext::new_missing(
3736 "ConntrackAttrs",
3737 "SeqAdjOrig",
3738 self.orig_loc,
3739 self.buf.as_ptr() as usize,
3740 ))
3741 }
3742 pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3743 let mut iter = self.clone();
3744 iter.pos = 0;
3745 for attr in iter {
3746 if let Ok(ConntrackAttrs::SeqAdjReply(val)) = attr {
3747 return Ok(val);
3748 }
3749 }
3750 Err(ErrorContext::new_missing(
3751 "ConntrackAttrs",
3752 "SeqAdjReply",
3753 self.orig_loc,
3754 self.buf.as_ptr() as usize,
3755 ))
3756 }
3757 #[doc = "obsolete\n"]
3758 pub fn get_secmark(&self) -> Result<&'a [u8], ErrorContext> {
3759 let mut iter = self.clone();
3760 iter.pos = 0;
3761 for attr in iter {
3762 if let Ok(ConntrackAttrs::Secmark(val)) = attr {
3763 return Ok(val);
3764 }
3765 }
3766 Err(ErrorContext::new_missing(
3767 "ConntrackAttrs",
3768 "Secmark",
3769 self.orig_loc,
3770 self.buf.as_ptr() as usize,
3771 ))
3772 }
3773 #[doc = "conntrack zone id\n"]
3774 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
3775 let mut iter = self.clone();
3776 iter.pos = 0;
3777 for attr in iter {
3778 if let Ok(ConntrackAttrs::Zone(val)) = attr {
3779 return Ok(val);
3780 }
3781 }
3782 Err(ErrorContext::new_missing(
3783 "ConntrackAttrs",
3784 "Zone",
3785 self.orig_loc,
3786 self.buf.as_ptr() as usize,
3787 ))
3788 }
3789 pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
3790 let mut iter = self.clone();
3791 iter.pos = 0;
3792 for attr in iter {
3793 if let Ok(ConntrackAttrs::Secctx(val)) = attr {
3794 return Ok(val);
3795 }
3796 }
3797 Err(ErrorContext::new_missing(
3798 "ConntrackAttrs",
3799 "Secctx",
3800 self.orig_loc,
3801 self.buf.as_ptr() as usize,
3802 ))
3803 }
3804 pub fn get_timestamp(&self) -> Result<u64, ErrorContext> {
3805 let mut iter = self.clone();
3806 iter.pos = 0;
3807 for attr in iter {
3808 if let Ok(ConntrackAttrs::Timestamp(val)) = attr {
3809 return Ok(val);
3810 }
3811 }
3812 Err(ErrorContext::new_missing(
3813 "ConntrackAttrs",
3814 "Timestamp",
3815 self.orig_loc,
3816 self.buf.as_ptr() as usize,
3817 ))
3818 }
3819 pub fn get_mark_mask(&self) -> Result<u32, ErrorContext> {
3820 let mut iter = self.clone();
3821 iter.pos = 0;
3822 for attr in iter {
3823 if let Ok(ConntrackAttrs::MarkMask(val)) = attr {
3824 return Ok(val);
3825 }
3826 }
3827 Err(ErrorContext::new_missing(
3828 "ConntrackAttrs",
3829 "MarkMask",
3830 self.orig_loc,
3831 self.buf.as_ptr() as usize,
3832 ))
3833 }
3834 pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
3835 let mut iter = self.clone();
3836 iter.pos = 0;
3837 for attr in iter {
3838 if let Ok(ConntrackAttrs::Labels(val)) = attr {
3839 return Ok(val);
3840 }
3841 }
3842 Err(ErrorContext::new_missing(
3843 "ConntrackAttrs",
3844 "Labels",
3845 self.orig_loc,
3846 self.buf.as_ptr() as usize,
3847 ))
3848 }
3849 pub fn get_labels_mask(&self) -> Result<&'a [u8], ErrorContext> {
3850 let mut iter = self.clone();
3851 iter.pos = 0;
3852 for attr in iter {
3853 if let Ok(ConntrackAttrs::LabelsMask(val)) = attr {
3854 return Ok(val);
3855 }
3856 }
3857 Err(ErrorContext::new_missing(
3858 "ConntrackAttrs",
3859 "LabelsMask",
3860 self.orig_loc,
3861 self.buf.as_ptr() as usize,
3862 ))
3863 }
3864 pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
3865 let mut iter = self.clone();
3866 iter.pos = 0;
3867 for attr in iter {
3868 if let Ok(ConntrackAttrs::Synproxy(val)) = attr {
3869 return Ok(val);
3870 }
3871 }
3872 Err(ErrorContext::new_missing(
3873 "ConntrackAttrs",
3874 "Synproxy",
3875 self.orig_loc,
3876 self.buf.as_ptr() as usize,
3877 ))
3878 }
3879 pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3880 let mut iter = self.clone();
3881 iter.pos = 0;
3882 for attr in iter {
3883 if let Ok(ConntrackAttrs::Filter(val)) = attr {
3884 return Ok(val);
3885 }
3886 }
3887 Err(ErrorContext::new_missing(
3888 "ConntrackAttrs",
3889 "Filter",
3890 self.orig_loc,
3891 self.buf.as_ptr() as usize,
3892 ))
3893 }
3894 #[doc = "conntrack flag bits to change\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
3895 pub fn get_status_mask(&self) -> Result<u32, ErrorContext> {
3896 let mut iter = self.clone();
3897 iter.pos = 0;
3898 for attr in iter {
3899 if let Ok(ConntrackAttrs::StatusMask(val)) = attr {
3900 return Ok(val);
3901 }
3902 }
3903 Err(ErrorContext::new_missing(
3904 "ConntrackAttrs",
3905 "StatusMask",
3906 self.orig_loc,
3907 self.buf.as_ptr() as usize,
3908 ))
3909 }
3910 pub fn get_timestamp_event(&self) -> Result<u64, ErrorContext> {
3911 let mut iter = self.clone();
3912 iter.pos = 0;
3913 for attr in iter {
3914 if let Ok(ConntrackAttrs::TimestampEvent(val)) = attr {
3915 return Ok(val);
3916 }
3917 }
3918 Err(ErrorContext::new_missing(
3919 "ConntrackAttrs",
3920 "TimestampEvent",
3921 self.orig_loc,
3922 self.buf.as_ptr() as usize,
3923 ))
3924 }
3925}
3926impl ConntrackAttrs<'_> {
3927 pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackAttrs<'a> {
3928 IterableConntrackAttrs::with_loc(buf, buf.as_ptr() as usize)
3929 }
3930 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3931 let res = match r#type {
3932 1u16 => "TupleOrig",
3933 2u16 => "TupleReply",
3934 3u16 => "Status",
3935 4u16 => "Protoinfo",
3936 5u16 => "Help",
3937 6u16 => "NatSrc",
3938 7u16 => "Timeout",
3939 8u16 => "Mark",
3940 9u16 => "CountersOrig",
3941 10u16 => "CountersReply",
3942 11u16 => "Use",
3943 12u16 => "Id",
3944 13u16 => "NatDst",
3945 14u16 => "TupleMaster",
3946 15u16 => "SeqAdjOrig",
3947 16u16 => "SeqAdjReply",
3948 17u16 => "Secmark",
3949 18u16 => "Zone",
3950 19u16 => "Secctx",
3951 20u16 => "Timestamp",
3952 21u16 => "MarkMask",
3953 22u16 => "Labels",
3954 23u16 => "LabelsMask",
3955 24u16 => "Synproxy",
3956 25u16 => "Filter",
3957 26u16 => "StatusMask",
3958 27u16 => "TimestampEvent",
3959 _ => return None,
3960 };
3961 Some(res)
3962 }
3963}
3964#[derive(Clone, Copy, Default)]
3965pub struct IterableConntrackAttrs<'a> {
3966 buf: &'a [u8],
3967 pos: usize,
3968 orig_loc: usize,
3969}
3970impl<'a> IterableConntrackAttrs<'a> {
3971 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3972 Self {
3973 buf,
3974 pos: 0,
3975 orig_loc,
3976 }
3977 }
3978 pub fn get_buf(&self) -> &'a [u8] {
3979 self.buf
3980 }
3981}
3982impl<'a> Iterator for IterableConntrackAttrs<'a> {
3983 type Item = Result<ConntrackAttrs<'a>, ErrorContext>;
3984 fn next(&mut self) -> Option<Self::Item> {
3985 let mut pos;
3986 let mut r#type;
3987 loop {
3988 pos = self.pos;
3989 r#type = None;
3990 if self.buf.len() == self.pos {
3991 return None;
3992 }
3993 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3994 self.pos = self.buf.len();
3995 break;
3996 };
3997 r#type = Some(header.r#type);
3998 let res = match header.r#type {
3999 1u16 => ConntrackAttrs::TupleOrig({
4000 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4001 let Some(val) = res else { break };
4002 val
4003 }),
4004 2u16 => ConntrackAttrs::TupleReply({
4005 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4006 let Some(val) = res else { break };
4007 val
4008 }),
4009 3u16 => ConntrackAttrs::Status({
4010 let res = parse_be_u32(next);
4011 let Some(val) = res else { break };
4012 val
4013 }),
4014 4u16 => ConntrackAttrs::Protoinfo({
4015 let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
4016 let Some(val) = res else { break };
4017 val
4018 }),
4019 5u16 => ConntrackAttrs::Help({
4020 let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
4021 let Some(val) = res else { break };
4022 val
4023 }),
4024 6u16 => ConntrackAttrs::NatSrc({
4025 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
4026 let Some(val) = res else { break };
4027 val
4028 }),
4029 7u16 => ConntrackAttrs::Timeout({
4030 let res = parse_be_u32(next);
4031 let Some(val) = res else { break };
4032 val
4033 }),
4034 8u16 => ConntrackAttrs::Mark({
4035 let res = parse_be_u32(next);
4036 let Some(val) = res else { break };
4037 val
4038 }),
4039 9u16 => ConntrackAttrs::CountersOrig({
4040 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
4041 let Some(val) = res else { break };
4042 val
4043 }),
4044 10u16 => ConntrackAttrs::CountersReply({
4045 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
4046 let Some(val) = res else { break };
4047 val
4048 }),
4049 11u16 => ConntrackAttrs::Use({
4050 let res = parse_be_u32(next);
4051 let Some(val) = res else { break };
4052 val
4053 }),
4054 12u16 => ConntrackAttrs::Id({
4055 let res = parse_be_u32(next);
4056 let Some(val) = res else { break };
4057 val
4058 }),
4059 13u16 => ConntrackAttrs::NatDst({
4060 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
4061 let Some(val) = res else { break };
4062 val
4063 }),
4064 14u16 => ConntrackAttrs::TupleMaster({
4065 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4066 let Some(val) = res else { break };
4067 val
4068 }),
4069 15u16 => ConntrackAttrs::SeqAdjOrig({
4070 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
4071 let Some(val) = res else { break };
4072 val
4073 }),
4074 16u16 => ConntrackAttrs::SeqAdjReply({
4075 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
4076 let Some(val) = res else { break };
4077 val
4078 }),
4079 17u16 => ConntrackAttrs::Secmark({
4080 let res = Some(next);
4081 let Some(val) = res else { break };
4082 val
4083 }),
4084 18u16 => ConntrackAttrs::Zone({
4085 let res = parse_be_u16(next);
4086 let Some(val) = res else { break };
4087 val
4088 }),
4089 19u16 => ConntrackAttrs::Secctx({
4090 let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
4091 let Some(val) = res else { break };
4092 val
4093 }),
4094 20u16 => ConntrackAttrs::Timestamp({
4095 let res = parse_be_u64(next);
4096 let Some(val) = res else { break };
4097 val
4098 }),
4099 21u16 => ConntrackAttrs::MarkMask({
4100 let res = parse_be_u32(next);
4101 let Some(val) = res else { break };
4102 val
4103 }),
4104 22u16 => ConntrackAttrs::Labels({
4105 let res = Some(next);
4106 let Some(val) = res else { break };
4107 val
4108 }),
4109 23u16 => ConntrackAttrs::LabelsMask({
4110 let res = Some(next);
4111 let Some(val) = res else { break };
4112 val
4113 }),
4114 24u16 => ConntrackAttrs::Synproxy({
4115 let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
4116 let Some(val) = res else { break };
4117 val
4118 }),
4119 25u16 => ConntrackAttrs::Filter({
4120 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
4121 let Some(val) = res else { break };
4122 val
4123 }),
4124 26u16 => ConntrackAttrs::StatusMask({
4125 let res = parse_be_u32(next);
4126 let Some(val) = res else { break };
4127 val
4128 }),
4129 27u16 => ConntrackAttrs::TimestampEvent({
4130 let res = parse_be_u64(next);
4131 let Some(val) = res else { break };
4132 val
4133 }),
4134 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4135 n => continue,
4136 };
4137 return Some(Ok(res));
4138 }
4139 Some(Err(ErrorContext::new(
4140 "ConntrackAttrs",
4141 r#type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4142 self.orig_loc,
4143 self.buf.as_ptr().wrapping_add(pos) as usize,
4144 )))
4145 }
4146}
4147impl<'a> std::fmt::Debug for IterableConntrackAttrs<'_> {
4148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4149 let mut fmt = f.debug_struct("ConntrackAttrs");
4150 for attr in self.clone() {
4151 let attr = match attr {
4152 Ok(a) => a,
4153 Err(err) => {
4154 fmt.finish()?;
4155 f.write_str("Err(")?;
4156 err.fmt(f)?;
4157 return f.write_str(")");
4158 }
4159 };
4160 match attr {
4161 ConntrackAttrs::TupleOrig(val) => fmt.field("TupleOrig", &val),
4162 ConntrackAttrs::TupleReply(val) => fmt.field("TupleReply", &val),
4163 ConntrackAttrs::Status(val) => {
4164 fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
4165 }
4166 ConntrackAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
4167 ConntrackAttrs::Help(val) => fmt.field("Help", &val),
4168 ConntrackAttrs::NatSrc(val) => fmt.field("NatSrc", &val),
4169 ConntrackAttrs::Timeout(val) => fmt.field("Timeout", &val),
4170 ConntrackAttrs::Mark(val) => fmt.field("Mark", &val),
4171 ConntrackAttrs::CountersOrig(val) => fmt.field("CountersOrig", &val),
4172 ConntrackAttrs::CountersReply(val) => fmt.field("CountersReply", &val),
4173 ConntrackAttrs::Use(val) => fmt.field("Use", &val),
4174 ConntrackAttrs::Id(val) => fmt.field("Id", &val),
4175 ConntrackAttrs::NatDst(val) => fmt.field("NatDst", &val),
4176 ConntrackAttrs::TupleMaster(val) => fmt.field("TupleMaster", &val),
4177 ConntrackAttrs::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
4178 ConntrackAttrs::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
4179 ConntrackAttrs::Secmark(val) => fmt.field("Secmark", &val),
4180 ConntrackAttrs::Zone(val) => fmt.field("Zone", &val),
4181 ConntrackAttrs::Secctx(val) => fmt.field("Secctx", &val),
4182 ConntrackAttrs::Timestamp(val) => fmt.field("Timestamp", &val),
4183 ConntrackAttrs::MarkMask(val) => fmt.field("MarkMask", &val),
4184 ConntrackAttrs::Labels(val) => fmt.field("Labels", &val),
4185 ConntrackAttrs::LabelsMask(val) => fmt.field("LabelsMask", &val),
4186 ConntrackAttrs::Synproxy(val) => fmt.field("Synproxy", &val),
4187 ConntrackAttrs::Filter(val) => fmt.field("Filter", &val),
4188 ConntrackAttrs::StatusMask(val) => fmt.field(
4189 "StatusMask",
4190 &FormatFlags(val.into(), NfCtStatus::from_value),
4191 ),
4192 ConntrackAttrs::TimestampEvent(val) => fmt.field("TimestampEvent", &val),
4193 };
4194 }
4195 fmt.finish()
4196 }
4197}
4198impl IterableConntrackAttrs<'_> {
4199 pub fn lookup_attr(
4200 &self,
4201 offset: usize,
4202 missing_type: Option<u16>,
4203 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4204 let mut stack = Vec::new();
4205 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4206 if missing_type.is_some() && cur == offset {
4207 stack.push(("ConntrackAttrs", offset));
4208 return (
4209 stack,
4210 missing_type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4211 );
4212 }
4213 if cur > offset || cur + self.buf.len() < offset {
4214 return (stack, None);
4215 }
4216 let mut attrs = self.clone();
4217 let mut last_off = cur + attrs.pos;
4218 let mut missing = None;
4219 while let Some(attr) = attrs.next() {
4220 let Ok(attr) = attr else { break };
4221 match attr {
4222 ConntrackAttrs::TupleOrig(val) => {
4223 (stack, missing) = val.lookup_attr(offset, missing_type);
4224 if !stack.is_empty() {
4225 break;
4226 }
4227 }
4228 ConntrackAttrs::TupleReply(val) => {
4229 (stack, missing) = val.lookup_attr(offset, missing_type);
4230 if !stack.is_empty() {
4231 break;
4232 }
4233 }
4234 ConntrackAttrs::Status(val) => {
4235 if last_off == offset {
4236 stack.push(("Status", last_off));
4237 break;
4238 }
4239 }
4240 ConntrackAttrs::Protoinfo(val) => {
4241 (stack, missing) = val.lookup_attr(offset, missing_type);
4242 if !stack.is_empty() {
4243 break;
4244 }
4245 }
4246 ConntrackAttrs::Help(val) => {
4247 (stack, missing) = val.lookup_attr(offset, missing_type);
4248 if !stack.is_empty() {
4249 break;
4250 }
4251 }
4252 ConntrackAttrs::NatSrc(val) => {
4253 (stack, missing) = val.lookup_attr(offset, missing_type);
4254 if !stack.is_empty() {
4255 break;
4256 }
4257 }
4258 ConntrackAttrs::Timeout(val) => {
4259 if last_off == offset {
4260 stack.push(("Timeout", last_off));
4261 break;
4262 }
4263 }
4264 ConntrackAttrs::Mark(val) => {
4265 if last_off == offset {
4266 stack.push(("Mark", last_off));
4267 break;
4268 }
4269 }
4270 ConntrackAttrs::CountersOrig(val) => {
4271 (stack, missing) = val.lookup_attr(offset, missing_type);
4272 if !stack.is_empty() {
4273 break;
4274 }
4275 }
4276 ConntrackAttrs::CountersReply(val) => {
4277 (stack, missing) = val.lookup_attr(offset, missing_type);
4278 if !stack.is_empty() {
4279 break;
4280 }
4281 }
4282 ConntrackAttrs::Use(val) => {
4283 if last_off == offset {
4284 stack.push(("Use", last_off));
4285 break;
4286 }
4287 }
4288 ConntrackAttrs::Id(val) => {
4289 if last_off == offset {
4290 stack.push(("Id", last_off));
4291 break;
4292 }
4293 }
4294 ConntrackAttrs::NatDst(val) => {
4295 (stack, missing) = val.lookup_attr(offset, missing_type);
4296 if !stack.is_empty() {
4297 break;
4298 }
4299 }
4300 ConntrackAttrs::TupleMaster(val) => {
4301 (stack, missing) = val.lookup_attr(offset, missing_type);
4302 if !stack.is_empty() {
4303 break;
4304 }
4305 }
4306 ConntrackAttrs::SeqAdjOrig(val) => {
4307 (stack, missing) = val.lookup_attr(offset, missing_type);
4308 if !stack.is_empty() {
4309 break;
4310 }
4311 }
4312 ConntrackAttrs::SeqAdjReply(val) => {
4313 (stack, missing) = val.lookup_attr(offset, missing_type);
4314 if !stack.is_empty() {
4315 break;
4316 }
4317 }
4318 ConntrackAttrs::Secmark(val) => {
4319 if last_off == offset {
4320 stack.push(("Secmark", last_off));
4321 break;
4322 }
4323 }
4324 ConntrackAttrs::Zone(val) => {
4325 if last_off == offset {
4326 stack.push(("Zone", last_off));
4327 break;
4328 }
4329 }
4330 ConntrackAttrs::Secctx(val) => {
4331 (stack, missing) = val.lookup_attr(offset, missing_type);
4332 if !stack.is_empty() {
4333 break;
4334 }
4335 }
4336 ConntrackAttrs::Timestamp(val) => {
4337 if last_off == offset {
4338 stack.push(("Timestamp", last_off));
4339 break;
4340 }
4341 }
4342 ConntrackAttrs::MarkMask(val) => {
4343 if last_off == offset {
4344 stack.push(("MarkMask", last_off));
4345 break;
4346 }
4347 }
4348 ConntrackAttrs::Labels(val) => {
4349 if last_off == offset {
4350 stack.push(("Labels", last_off));
4351 break;
4352 }
4353 }
4354 ConntrackAttrs::LabelsMask(val) => {
4355 if last_off == offset {
4356 stack.push(("LabelsMask", last_off));
4357 break;
4358 }
4359 }
4360 ConntrackAttrs::Synproxy(val) => {
4361 (stack, missing) = val.lookup_attr(offset, missing_type);
4362 if !stack.is_empty() {
4363 break;
4364 }
4365 }
4366 ConntrackAttrs::Filter(val) => {
4367 (stack, missing) = val.lookup_attr(offset, missing_type);
4368 if !stack.is_empty() {
4369 break;
4370 }
4371 }
4372 ConntrackAttrs::StatusMask(val) => {
4373 if last_off == offset {
4374 stack.push(("StatusMask", last_off));
4375 break;
4376 }
4377 }
4378 ConntrackAttrs::TimestampEvent(val) => {
4379 if last_off == offset {
4380 stack.push(("TimestampEvent", last_off));
4381 break;
4382 }
4383 }
4384 _ => {}
4385 };
4386 last_off = cur + attrs.pos;
4387 }
4388 if !stack.is_empty() {
4389 stack.push(("ConntrackAttrs", cur));
4390 }
4391 (stack, missing)
4392 }
4393}
4394#[derive(Clone)]
4395pub enum ConntrackStatsAttrs {
4396 #[doc = "obsolete\n"]
4397 Searched(u32),
4398 Found(u32),
4399 #[doc = "obsolete\n"]
4400 New(u32),
4401 #[doc = "obsolete\n"]
4402 Invalid(u32),
4403 #[doc = "obsolete\n"]
4404 Ignore(u32),
4405 #[doc = "obsolete\n"]
4406 Delete(u32),
4407 #[doc = "obsolete\n"]
4408 DeleteList(u32),
4409 Insert(u32),
4410 InsertFailed(u32),
4411 Drop(u32),
4412 EarlyDrop(u32),
4413 Error(u32),
4414 SearchRestart(u32),
4415 ClashResolve(u32),
4416 ChainToolong(u32),
4417}
4418impl<'a> IterableConntrackStatsAttrs<'a> {
4419 #[doc = "obsolete\n"]
4420 pub fn get_searched(&self) -> Result<u32, ErrorContext> {
4421 let mut iter = self.clone();
4422 iter.pos = 0;
4423 for attr in iter {
4424 if let Ok(ConntrackStatsAttrs::Searched(val)) = attr {
4425 return Ok(val);
4426 }
4427 }
4428 Err(ErrorContext::new_missing(
4429 "ConntrackStatsAttrs",
4430 "Searched",
4431 self.orig_loc,
4432 self.buf.as_ptr() as usize,
4433 ))
4434 }
4435 pub fn get_found(&self) -> Result<u32, ErrorContext> {
4436 let mut iter = self.clone();
4437 iter.pos = 0;
4438 for attr in iter {
4439 if let Ok(ConntrackStatsAttrs::Found(val)) = attr {
4440 return Ok(val);
4441 }
4442 }
4443 Err(ErrorContext::new_missing(
4444 "ConntrackStatsAttrs",
4445 "Found",
4446 self.orig_loc,
4447 self.buf.as_ptr() as usize,
4448 ))
4449 }
4450 #[doc = "obsolete\n"]
4451 pub fn get_new(&self) -> Result<u32, ErrorContext> {
4452 let mut iter = self.clone();
4453 iter.pos = 0;
4454 for attr in iter {
4455 if let Ok(ConntrackStatsAttrs::New(val)) = attr {
4456 return Ok(val);
4457 }
4458 }
4459 Err(ErrorContext::new_missing(
4460 "ConntrackStatsAttrs",
4461 "New",
4462 self.orig_loc,
4463 self.buf.as_ptr() as usize,
4464 ))
4465 }
4466 #[doc = "obsolete\n"]
4467 pub fn get_invalid(&self) -> Result<u32, ErrorContext> {
4468 let mut iter = self.clone();
4469 iter.pos = 0;
4470 for attr in iter {
4471 if let Ok(ConntrackStatsAttrs::Invalid(val)) = attr {
4472 return Ok(val);
4473 }
4474 }
4475 Err(ErrorContext::new_missing(
4476 "ConntrackStatsAttrs",
4477 "Invalid",
4478 self.orig_loc,
4479 self.buf.as_ptr() as usize,
4480 ))
4481 }
4482 #[doc = "obsolete\n"]
4483 pub fn get_ignore(&self) -> Result<u32, ErrorContext> {
4484 let mut iter = self.clone();
4485 iter.pos = 0;
4486 for attr in iter {
4487 if let Ok(ConntrackStatsAttrs::Ignore(val)) = attr {
4488 return Ok(val);
4489 }
4490 }
4491 Err(ErrorContext::new_missing(
4492 "ConntrackStatsAttrs",
4493 "Ignore",
4494 self.orig_loc,
4495 self.buf.as_ptr() as usize,
4496 ))
4497 }
4498 #[doc = "obsolete\n"]
4499 pub fn get_delete(&self) -> Result<u32, ErrorContext> {
4500 let mut iter = self.clone();
4501 iter.pos = 0;
4502 for attr in iter {
4503 if let Ok(ConntrackStatsAttrs::Delete(val)) = attr {
4504 return Ok(val);
4505 }
4506 }
4507 Err(ErrorContext::new_missing(
4508 "ConntrackStatsAttrs",
4509 "Delete",
4510 self.orig_loc,
4511 self.buf.as_ptr() as usize,
4512 ))
4513 }
4514 #[doc = "obsolete\n"]
4515 pub fn get_delete_list(&self) -> Result<u32, ErrorContext> {
4516 let mut iter = self.clone();
4517 iter.pos = 0;
4518 for attr in iter {
4519 if let Ok(ConntrackStatsAttrs::DeleteList(val)) = attr {
4520 return Ok(val);
4521 }
4522 }
4523 Err(ErrorContext::new_missing(
4524 "ConntrackStatsAttrs",
4525 "DeleteList",
4526 self.orig_loc,
4527 self.buf.as_ptr() as usize,
4528 ))
4529 }
4530 pub fn get_insert(&self) -> Result<u32, ErrorContext> {
4531 let mut iter = self.clone();
4532 iter.pos = 0;
4533 for attr in iter {
4534 if let Ok(ConntrackStatsAttrs::Insert(val)) = attr {
4535 return Ok(val);
4536 }
4537 }
4538 Err(ErrorContext::new_missing(
4539 "ConntrackStatsAttrs",
4540 "Insert",
4541 self.orig_loc,
4542 self.buf.as_ptr() as usize,
4543 ))
4544 }
4545 pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
4546 let mut iter = self.clone();
4547 iter.pos = 0;
4548 for attr in iter {
4549 if let Ok(ConntrackStatsAttrs::InsertFailed(val)) = attr {
4550 return Ok(val);
4551 }
4552 }
4553 Err(ErrorContext::new_missing(
4554 "ConntrackStatsAttrs",
4555 "InsertFailed",
4556 self.orig_loc,
4557 self.buf.as_ptr() as usize,
4558 ))
4559 }
4560 pub fn get_drop(&self) -> Result<u32, ErrorContext> {
4561 let mut iter = self.clone();
4562 iter.pos = 0;
4563 for attr in iter {
4564 if let Ok(ConntrackStatsAttrs::Drop(val)) = attr {
4565 return Ok(val);
4566 }
4567 }
4568 Err(ErrorContext::new_missing(
4569 "ConntrackStatsAttrs",
4570 "Drop",
4571 self.orig_loc,
4572 self.buf.as_ptr() as usize,
4573 ))
4574 }
4575 pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
4576 let mut iter = self.clone();
4577 iter.pos = 0;
4578 for attr in iter {
4579 if let Ok(ConntrackStatsAttrs::EarlyDrop(val)) = attr {
4580 return Ok(val);
4581 }
4582 }
4583 Err(ErrorContext::new_missing(
4584 "ConntrackStatsAttrs",
4585 "EarlyDrop",
4586 self.orig_loc,
4587 self.buf.as_ptr() as usize,
4588 ))
4589 }
4590 pub fn get_error(&self) -> Result<u32, ErrorContext> {
4591 let mut iter = self.clone();
4592 iter.pos = 0;
4593 for attr in iter {
4594 if let Ok(ConntrackStatsAttrs::Error(val)) = attr {
4595 return Ok(val);
4596 }
4597 }
4598 Err(ErrorContext::new_missing(
4599 "ConntrackStatsAttrs",
4600 "Error",
4601 self.orig_loc,
4602 self.buf.as_ptr() as usize,
4603 ))
4604 }
4605 pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
4606 let mut iter = self.clone();
4607 iter.pos = 0;
4608 for attr in iter {
4609 if let Ok(ConntrackStatsAttrs::SearchRestart(val)) = attr {
4610 return Ok(val);
4611 }
4612 }
4613 Err(ErrorContext::new_missing(
4614 "ConntrackStatsAttrs",
4615 "SearchRestart",
4616 self.orig_loc,
4617 self.buf.as_ptr() as usize,
4618 ))
4619 }
4620 pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
4621 let mut iter = self.clone();
4622 iter.pos = 0;
4623 for attr in iter {
4624 if let Ok(ConntrackStatsAttrs::ClashResolve(val)) = attr {
4625 return Ok(val);
4626 }
4627 }
4628 Err(ErrorContext::new_missing(
4629 "ConntrackStatsAttrs",
4630 "ClashResolve",
4631 self.orig_loc,
4632 self.buf.as_ptr() as usize,
4633 ))
4634 }
4635 pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
4636 let mut iter = self.clone();
4637 iter.pos = 0;
4638 for attr in iter {
4639 if let Ok(ConntrackStatsAttrs::ChainToolong(val)) = attr {
4640 return Ok(val);
4641 }
4642 }
4643 Err(ErrorContext::new_missing(
4644 "ConntrackStatsAttrs",
4645 "ChainToolong",
4646 self.orig_loc,
4647 self.buf.as_ptr() as usize,
4648 ))
4649 }
4650}
4651impl ConntrackStatsAttrs {
4652 pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackStatsAttrs<'a> {
4653 IterableConntrackStatsAttrs::with_loc(buf, buf.as_ptr() as usize)
4654 }
4655 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4656 let res = match r#type {
4657 1u16 => "Searched",
4658 2u16 => "Found",
4659 3u16 => "New",
4660 4u16 => "Invalid",
4661 5u16 => "Ignore",
4662 6u16 => "Delete",
4663 7u16 => "DeleteList",
4664 8u16 => "Insert",
4665 9u16 => "InsertFailed",
4666 10u16 => "Drop",
4667 11u16 => "EarlyDrop",
4668 12u16 => "Error",
4669 13u16 => "SearchRestart",
4670 14u16 => "ClashResolve",
4671 15u16 => "ChainToolong",
4672 _ => return None,
4673 };
4674 Some(res)
4675 }
4676}
4677#[derive(Clone, Copy, Default)]
4678pub struct IterableConntrackStatsAttrs<'a> {
4679 buf: &'a [u8],
4680 pos: usize,
4681 orig_loc: usize,
4682}
4683impl<'a> IterableConntrackStatsAttrs<'a> {
4684 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4685 Self {
4686 buf,
4687 pos: 0,
4688 orig_loc,
4689 }
4690 }
4691 pub fn get_buf(&self) -> &'a [u8] {
4692 self.buf
4693 }
4694}
4695impl<'a> Iterator for IterableConntrackStatsAttrs<'a> {
4696 type Item = Result<ConntrackStatsAttrs, ErrorContext>;
4697 fn next(&mut self) -> Option<Self::Item> {
4698 let mut pos;
4699 let mut r#type;
4700 loop {
4701 pos = self.pos;
4702 r#type = None;
4703 if self.buf.len() == self.pos {
4704 return None;
4705 }
4706 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4707 self.pos = self.buf.len();
4708 break;
4709 };
4710 r#type = Some(header.r#type);
4711 let res = match header.r#type {
4712 1u16 => ConntrackStatsAttrs::Searched({
4713 let res = parse_be_u32(next);
4714 let Some(val) = res else { break };
4715 val
4716 }),
4717 2u16 => ConntrackStatsAttrs::Found({
4718 let res = parse_be_u32(next);
4719 let Some(val) = res else { break };
4720 val
4721 }),
4722 3u16 => ConntrackStatsAttrs::New({
4723 let res = parse_be_u32(next);
4724 let Some(val) = res else { break };
4725 val
4726 }),
4727 4u16 => ConntrackStatsAttrs::Invalid({
4728 let res = parse_be_u32(next);
4729 let Some(val) = res else { break };
4730 val
4731 }),
4732 5u16 => ConntrackStatsAttrs::Ignore({
4733 let res = parse_be_u32(next);
4734 let Some(val) = res else { break };
4735 val
4736 }),
4737 6u16 => ConntrackStatsAttrs::Delete({
4738 let res = parse_be_u32(next);
4739 let Some(val) = res else { break };
4740 val
4741 }),
4742 7u16 => ConntrackStatsAttrs::DeleteList({
4743 let res = parse_be_u32(next);
4744 let Some(val) = res else { break };
4745 val
4746 }),
4747 8u16 => ConntrackStatsAttrs::Insert({
4748 let res = parse_be_u32(next);
4749 let Some(val) = res else { break };
4750 val
4751 }),
4752 9u16 => ConntrackStatsAttrs::InsertFailed({
4753 let res = parse_be_u32(next);
4754 let Some(val) = res else { break };
4755 val
4756 }),
4757 10u16 => ConntrackStatsAttrs::Drop({
4758 let res = parse_be_u32(next);
4759 let Some(val) = res else { break };
4760 val
4761 }),
4762 11u16 => ConntrackStatsAttrs::EarlyDrop({
4763 let res = parse_be_u32(next);
4764 let Some(val) = res else { break };
4765 val
4766 }),
4767 12u16 => ConntrackStatsAttrs::Error({
4768 let res = parse_be_u32(next);
4769 let Some(val) = res else { break };
4770 val
4771 }),
4772 13u16 => ConntrackStatsAttrs::SearchRestart({
4773 let res = parse_be_u32(next);
4774 let Some(val) = res else { break };
4775 val
4776 }),
4777 14u16 => ConntrackStatsAttrs::ClashResolve({
4778 let res = parse_be_u32(next);
4779 let Some(val) = res else { break };
4780 val
4781 }),
4782 15u16 => ConntrackStatsAttrs::ChainToolong({
4783 let res = parse_be_u32(next);
4784 let Some(val) = res else { break };
4785 val
4786 }),
4787 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4788 n => continue,
4789 };
4790 return Some(Ok(res));
4791 }
4792 Some(Err(ErrorContext::new(
4793 "ConntrackStatsAttrs",
4794 r#type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4795 self.orig_loc,
4796 self.buf.as_ptr().wrapping_add(pos) as usize,
4797 )))
4798 }
4799}
4800impl std::fmt::Debug for IterableConntrackStatsAttrs<'_> {
4801 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4802 let mut fmt = f.debug_struct("ConntrackStatsAttrs");
4803 for attr in self.clone() {
4804 let attr = match attr {
4805 Ok(a) => a,
4806 Err(err) => {
4807 fmt.finish()?;
4808 f.write_str("Err(")?;
4809 err.fmt(f)?;
4810 return f.write_str(")");
4811 }
4812 };
4813 match attr {
4814 ConntrackStatsAttrs::Searched(val) => fmt.field("Searched", &val),
4815 ConntrackStatsAttrs::Found(val) => fmt.field("Found", &val),
4816 ConntrackStatsAttrs::New(val) => fmt.field("New", &val),
4817 ConntrackStatsAttrs::Invalid(val) => fmt.field("Invalid", &val),
4818 ConntrackStatsAttrs::Ignore(val) => fmt.field("Ignore", &val),
4819 ConntrackStatsAttrs::Delete(val) => fmt.field("Delete", &val),
4820 ConntrackStatsAttrs::DeleteList(val) => fmt.field("DeleteList", &val),
4821 ConntrackStatsAttrs::Insert(val) => fmt.field("Insert", &val),
4822 ConntrackStatsAttrs::InsertFailed(val) => fmt.field("InsertFailed", &val),
4823 ConntrackStatsAttrs::Drop(val) => fmt.field("Drop", &val),
4824 ConntrackStatsAttrs::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
4825 ConntrackStatsAttrs::Error(val) => fmt.field("Error", &val),
4826 ConntrackStatsAttrs::SearchRestart(val) => fmt.field("SearchRestart", &val),
4827 ConntrackStatsAttrs::ClashResolve(val) => fmt.field("ClashResolve", &val),
4828 ConntrackStatsAttrs::ChainToolong(val) => fmt.field("ChainToolong", &val),
4829 };
4830 }
4831 fmt.finish()
4832 }
4833}
4834impl IterableConntrackStatsAttrs<'_> {
4835 pub fn lookup_attr(
4836 &self,
4837 offset: usize,
4838 missing_type: Option<u16>,
4839 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4840 let mut stack = Vec::new();
4841 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4842 if missing_type.is_some() && cur == offset {
4843 stack.push(("ConntrackStatsAttrs", offset));
4844 return (
4845 stack,
4846 missing_type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4847 );
4848 }
4849 if cur > offset || cur + self.buf.len() < offset {
4850 return (stack, None);
4851 }
4852 let mut attrs = self.clone();
4853 let mut last_off = cur + attrs.pos;
4854 while let Some(attr) = attrs.next() {
4855 let Ok(attr) = attr else { break };
4856 match attr {
4857 ConntrackStatsAttrs::Searched(val) => {
4858 if last_off == offset {
4859 stack.push(("Searched", last_off));
4860 break;
4861 }
4862 }
4863 ConntrackStatsAttrs::Found(val) => {
4864 if last_off == offset {
4865 stack.push(("Found", last_off));
4866 break;
4867 }
4868 }
4869 ConntrackStatsAttrs::New(val) => {
4870 if last_off == offset {
4871 stack.push(("New", last_off));
4872 break;
4873 }
4874 }
4875 ConntrackStatsAttrs::Invalid(val) => {
4876 if last_off == offset {
4877 stack.push(("Invalid", last_off));
4878 break;
4879 }
4880 }
4881 ConntrackStatsAttrs::Ignore(val) => {
4882 if last_off == offset {
4883 stack.push(("Ignore", last_off));
4884 break;
4885 }
4886 }
4887 ConntrackStatsAttrs::Delete(val) => {
4888 if last_off == offset {
4889 stack.push(("Delete", last_off));
4890 break;
4891 }
4892 }
4893 ConntrackStatsAttrs::DeleteList(val) => {
4894 if last_off == offset {
4895 stack.push(("DeleteList", last_off));
4896 break;
4897 }
4898 }
4899 ConntrackStatsAttrs::Insert(val) => {
4900 if last_off == offset {
4901 stack.push(("Insert", last_off));
4902 break;
4903 }
4904 }
4905 ConntrackStatsAttrs::InsertFailed(val) => {
4906 if last_off == offset {
4907 stack.push(("InsertFailed", last_off));
4908 break;
4909 }
4910 }
4911 ConntrackStatsAttrs::Drop(val) => {
4912 if last_off == offset {
4913 stack.push(("Drop", last_off));
4914 break;
4915 }
4916 }
4917 ConntrackStatsAttrs::EarlyDrop(val) => {
4918 if last_off == offset {
4919 stack.push(("EarlyDrop", last_off));
4920 break;
4921 }
4922 }
4923 ConntrackStatsAttrs::Error(val) => {
4924 if last_off == offset {
4925 stack.push(("Error", last_off));
4926 break;
4927 }
4928 }
4929 ConntrackStatsAttrs::SearchRestart(val) => {
4930 if last_off == offset {
4931 stack.push(("SearchRestart", last_off));
4932 break;
4933 }
4934 }
4935 ConntrackStatsAttrs::ClashResolve(val) => {
4936 if last_off == offset {
4937 stack.push(("ClashResolve", last_off));
4938 break;
4939 }
4940 }
4941 ConntrackStatsAttrs::ChainToolong(val) => {
4942 if last_off == offset {
4943 stack.push(("ChainToolong", last_off));
4944 break;
4945 }
4946 }
4947 _ => {}
4948 };
4949 last_off = cur + attrs.pos;
4950 }
4951 if !stack.is_empty() {
4952 stack.push(("ConntrackStatsAttrs", cur));
4953 }
4954 (stack, None)
4955 }
4956}
4957pub struct PushCounterAttrs<Prev: Pusher> {
4958 pub(crate) prev: Option<Prev>,
4959 pub(crate) header_offset: Option<usize>,
4960}
4961impl<Prev: Pusher> Pusher for PushCounterAttrs<Prev> {
4962 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
4963 self.prev.as_mut().unwrap().as_vec_mut()
4964 }
4965 fn as_vec(&self) -> &Vec<u8> {
4966 self.prev.as_ref().unwrap().as_vec()
4967 }
4968}
4969impl<Prev: Pusher> PushCounterAttrs<Prev> {
4970 pub fn new(prev: Prev) -> Self {
4971 Self {
4972 prev: Some(prev),
4973 header_offset: None,
4974 }
4975 }
4976 pub fn end_nested(mut self) -> Prev {
4977 let mut prev = self.prev.take().unwrap();
4978 if let Some(header_offset) = &self.header_offset {
4979 finalize_nested_header(prev.as_vec_mut(), *header_offset);
4980 }
4981 prev
4982 }
4983 pub fn push_packets(mut self, value: u64) -> Self {
4984 push_header(self.as_vec_mut(), 1u16, 8 as u16);
4985 self.as_vec_mut().extend(value.to_be_bytes());
4986 self
4987 }
4988 pub fn push_bytes(mut self, value: u64) -> Self {
4989 push_header(self.as_vec_mut(), 2u16, 8 as u16);
4990 self.as_vec_mut().extend(value.to_be_bytes());
4991 self
4992 }
4993 pub fn push_packets_old(mut self, value: u32) -> Self {
4994 push_header(self.as_vec_mut(), 3u16, 4 as u16);
4995 self.as_vec_mut().extend(value.to_ne_bytes());
4996 self
4997 }
4998 pub fn push_bytes_old(mut self, value: u32) -> Self {
4999 push_header(self.as_vec_mut(), 4u16, 4 as u16);
5000 self.as_vec_mut().extend(value.to_ne_bytes());
5001 self
5002 }
5003 pub fn push_pad(mut self, value: &[u8]) -> Self {
5004 push_header(self.as_vec_mut(), 5u16, value.len() as u16);
5005 self.as_vec_mut().extend(value);
5006 self
5007 }
5008}
5009impl<Prev: Pusher> Drop for PushCounterAttrs<Prev> {
5010 fn drop(&mut self) {
5011 if let Some(prev) = &mut self.prev {
5012 if let Some(header_offset) = &self.header_offset {
5013 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5014 }
5015 }
5016 }
5017}
5018pub struct PushTupleProtoAttrs<Prev: Pusher> {
5019 pub(crate) prev: Option<Prev>,
5020 pub(crate) header_offset: Option<usize>,
5021}
5022impl<Prev: Pusher> Pusher for PushTupleProtoAttrs<Prev> {
5023 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5024 self.prev.as_mut().unwrap().as_vec_mut()
5025 }
5026 fn as_vec(&self) -> &Vec<u8> {
5027 self.prev.as_ref().unwrap().as_vec()
5028 }
5029}
5030impl<Prev: Pusher> PushTupleProtoAttrs<Prev> {
5031 pub fn new(prev: Prev) -> Self {
5032 Self {
5033 prev: Some(prev),
5034 header_offset: None,
5035 }
5036 }
5037 pub fn end_nested(mut self) -> Prev {
5038 let mut prev = self.prev.take().unwrap();
5039 if let Some(header_offset) = &self.header_offset {
5040 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5041 }
5042 prev
5043 }
5044 #[doc = "l4 protocol number\n"]
5045 pub fn push_proto_num(mut self, value: u8) -> Self {
5046 push_header(self.as_vec_mut(), 1u16, 1 as u16);
5047 self.as_vec_mut().extend(value.to_ne_bytes());
5048 self
5049 }
5050 #[doc = "l4 source port\n"]
5051 pub fn push_proto_src_port(mut self, value: u16) -> Self {
5052 push_header(self.as_vec_mut(), 2u16, 2 as u16);
5053 self.as_vec_mut().extend(value.to_be_bytes());
5054 self
5055 }
5056 #[doc = "l4 source port\n"]
5057 pub fn push_proto_dst_port(mut self, value: u16) -> Self {
5058 push_header(self.as_vec_mut(), 3u16, 2 as u16);
5059 self.as_vec_mut().extend(value.to_be_bytes());
5060 self
5061 }
5062 #[doc = "l4 icmp id\n"]
5063 pub fn push_proto_icmp_id(mut self, value: u16) -> Self {
5064 push_header(self.as_vec_mut(), 4u16, 2 as u16);
5065 self.as_vec_mut().extend(value.to_be_bytes());
5066 self
5067 }
5068 pub fn push_proto_icmp_type(mut self, value: u8) -> Self {
5069 push_header(self.as_vec_mut(), 5u16, 1 as u16);
5070 self.as_vec_mut().extend(value.to_ne_bytes());
5071 self
5072 }
5073 pub fn push_proto_icmp_code(mut self, value: u8) -> Self {
5074 push_header(self.as_vec_mut(), 6u16, 1 as u16);
5075 self.as_vec_mut().extend(value.to_ne_bytes());
5076 self
5077 }
5078 #[doc = "l4 icmp id\n"]
5079 pub fn push_proto_icmpv6_id(mut self, value: u16) -> Self {
5080 push_header(self.as_vec_mut(), 7u16, 2 as u16);
5081 self.as_vec_mut().extend(value.to_be_bytes());
5082 self
5083 }
5084 pub fn push_proto_icmpv6_type(mut self, value: u8) -> Self {
5085 push_header(self.as_vec_mut(), 8u16, 1 as u16);
5086 self.as_vec_mut().extend(value.to_ne_bytes());
5087 self
5088 }
5089 pub fn push_proto_icmpv6_code(mut self, value: u8) -> Self {
5090 push_header(self.as_vec_mut(), 9u16, 1 as u16);
5091 self.as_vec_mut().extend(value.to_ne_bytes());
5092 self
5093 }
5094}
5095impl<Prev: Pusher> Drop for PushTupleProtoAttrs<Prev> {
5096 fn drop(&mut self) {
5097 if let Some(prev) = &mut self.prev {
5098 if let Some(header_offset) = &self.header_offset {
5099 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5100 }
5101 }
5102 }
5103}
5104pub struct PushTupleIpAttrs<Prev: Pusher> {
5105 pub(crate) prev: Option<Prev>,
5106 pub(crate) header_offset: Option<usize>,
5107}
5108impl<Prev: Pusher> Pusher for PushTupleIpAttrs<Prev> {
5109 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5110 self.prev.as_mut().unwrap().as_vec_mut()
5111 }
5112 fn as_vec(&self) -> &Vec<u8> {
5113 self.prev.as_ref().unwrap().as_vec()
5114 }
5115}
5116impl<Prev: Pusher> PushTupleIpAttrs<Prev> {
5117 pub fn new(prev: Prev) -> Self {
5118 Self {
5119 prev: Some(prev),
5120 header_offset: None,
5121 }
5122 }
5123 pub fn end_nested(mut self) -> Prev {
5124 let mut prev = self.prev.take().unwrap();
5125 if let Some(header_offset) = &self.header_offset {
5126 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5127 }
5128 prev
5129 }
5130 #[doc = "ipv4 source address\n"]
5131 pub fn push_ip_v4_src(mut self, value: std::net::Ipv4Addr) -> Self {
5132 push_header(self.as_vec_mut(), 1u16, 4 as u16);
5133 self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
5134 self
5135 }
5136 #[doc = "ipv4 destination address\n"]
5137 pub fn push_ip_v4_dst(mut self, value: std::net::Ipv4Addr) -> Self {
5138 push_header(self.as_vec_mut(), 2u16, 4 as u16);
5139 self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
5140 self
5141 }
5142 #[doc = "ipv6 source address\n"]
5143 pub fn push_ip_v6_src(mut self, value: std::net::Ipv6Addr) -> Self {
5144 push_header(self.as_vec_mut(), 3u16, 16 as u16);
5145 self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
5146 self
5147 }
5148 #[doc = "ipv6 destination address\n"]
5149 pub fn push_ip_v6_dst(mut self, value: std::net::Ipv6Addr) -> Self {
5150 push_header(self.as_vec_mut(), 4u16, 16 as u16);
5151 self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
5152 self
5153 }
5154}
5155impl<Prev: Pusher> Drop for PushTupleIpAttrs<Prev> {
5156 fn drop(&mut self) {
5157 if let Some(prev) = &mut self.prev {
5158 if let Some(header_offset) = &self.header_offset {
5159 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5160 }
5161 }
5162 }
5163}
5164pub struct PushTupleAttrs<Prev: Pusher> {
5165 pub(crate) prev: Option<Prev>,
5166 pub(crate) header_offset: Option<usize>,
5167}
5168impl<Prev: Pusher> Pusher for PushTupleAttrs<Prev> {
5169 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5170 self.prev.as_mut().unwrap().as_vec_mut()
5171 }
5172 fn as_vec(&self) -> &Vec<u8> {
5173 self.prev.as_ref().unwrap().as_vec()
5174 }
5175}
5176impl<Prev: Pusher> PushTupleAttrs<Prev> {
5177 pub fn new(prev: Prev) -> Self {
5178 Self {
5179 prev: Some(prev),
5180 header_offset: None,
5181 }
5182 }
5183 pub fn end_nested(mut self) -> Prev {
5184 let mut prev = self.prev.take().unwrap();
5185 if let Some(header_offset) = &self.header_offset {
5186 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5187 }
5188 prev
5189 }
5190 #[doc = "conntrack l3 information\n"]
5191 pub fn nested_tuple_ip(mut self) -> PushTupleIpAttrs<Self> {
5192 let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
5193 PushTupleIpAttrs {
5194 prev: Some(self),
5195 header_offset: Some(header_offset),
5196 }
5197 }
5198 #[doc = "conntrack l4 information\n"]
5199 pub fn nested_tuple_proto(mut self) -> PushTupleProtoAttrs<Self> {
5200 let header_offset = push_nested_header(self.as_vec_mut(), 2u16);
5201 PushTupleProtoAttrs {
5202 prev: Some(self),
5203 header_offset: Some(header_offset),
5204 }
5205 }
5206 #[doc = "conntrack zone id\n"]
5207 pub fn push_tuple_zone(mut self, value: u16) -> Self {
5208 push_header(self.as_vec_mut(), 3u16, 2 as u16);
5209 self.as_vec_mut().extend(value.to_be_bytes());
5210 self
5211 }
5212}
5213impl<Prev: Pusher> Drop for PushTupleAttrs<Prev> {
5214 fn drop(&mut self) {
5215 if let Some(prev) = &mut self.prev {
5216 if let Some(header_offset) = &self.header_offset {
5217 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5218 }
5219 }
5220 }
5221}
5222pub struct PushProtoinfoTcpAttrs<Prev: Pusher> {
5223 pub(crate) prev: Option<Prev>,
5224 pub(crate) header_offset: Option<usize>,
5225}
5226impl<Prev: Pusher> Pusher for PushProtoinfoTcpAttrs<Prev> {
5227 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5228 self.prev.as_mut().unwrap().as_vec_mut()
5229 }
5230 fn as_vec(&self) -> &Vec<u8> {
5231 self.prev.as_ref().unwrap().as_vec()
5232 }
5233}
5234impl<Prev: Pusher> PushProtoinfoTcpAttrs<Prev> {
5235 pub fn new(prev: Prev) -> Self {
5236 Self {
5237 prev: Some(prev),
5238 header_offset: None,
5239 }
5240 }
5241 pub fn end_nested(mut self) -> Prev {
5242 let mut prev = self.prev.take().unwrap();
5243 if let Some(header_offset) = &self.header_offset {
5244 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5245 }
5246 prev
5247 }
5248 #[doc = "tcp connection state\n\nAssociated type: [`NfCtTcpState`] (enum)"]
5249 pub fn push_tcp_state(mut self, value: u8) -> Self {
5250 push_header(self.as_vec_mut(), 1u16, 1 as u16);
5251 self.as_vec_mut().extend(value.to_ne_bytes());
5252 self
5253 }
5254 #[doc = "window scaling factor in original direction\n"]
5255 pub fn push_tcp_wscale_original(mut self, value: u8) -> Self {
5256 push_header(self.as_vec_mut(), 2u16, 1 as u16);
5257 self.as_vec_mut().extend(value.to_ne_bytes());
5258 self
5259 }
5260 #[doc = "window scaling factor in reply direction\n"]
5261 pub fn push_tcp_wscale_reply(mut self, value: u8) -> Self {
5262 push_header(self.as_vec_mut(), 3u16, 1 as u16);
5263 self.as_vec_mut().extend(value.to_ne_bytes());
5264 self
5265 }
5266 pub fn push_tcp_flags_original(mut self, value: NfCtTcpFlagsMask) -> Self {
5267 push_header(self.as_vec_mut(), 4u16, value.as_slice().len() as u16);
5268 self.as_vec_mut().extend(value.as_slice());
5269 self
5270 }
5271 pub fn push_tcp_flags_reply(mut self, value: NfCtTcpFlagsMask) -> Self {
5272 push_header(self.as_vec_mut(), 5u16, value.as_slice().len() as u16);
5273 self.as_vec_mut().extend(value.as_slice());
5274 self
5275 }
5276}
5277impl<Prev: Pusher> Drop for PushProtoinfoTcpAttrs<Prev> {
5278 fn drop(&mut self) {
5279 if let Some(prev) = &mut self.prev {
5280 if let Some(header_offset) = &self.header_offset {
5281 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5282 }
5283 }
5284 }
5285}
5286pub struct PushProtoinfoDccpAttrs<Prev: Pusher> {
5287 pub(crate) prev: Option<Prev>,
5288 pub(crate) header_offset: Option<usize>,
5289}
5290impl<Prev: Pusher> Pusher for PushProtoinfoDccpAttrs<Prev> {
5291 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5292 self.prev.as_mut().unwrap().as_vec_mut()
5293 }
5294 fn as_vec(&self) -> &Vec<u8> {
5295 self.prev.as_ref().unwrap().as_vec()
5296 }
5297}
5298impl<Prev: Pusher> PushProtoinfoDccpAttrs<Prev> {
5299 pub fn new(prev: Prev) -> Self {
5300 Self {
5301 prev: Some(prev),
5302 header_offset: None,
5303 }
5304 }
5305 pub fn end_nested(mut self) -> Prev {
5306 let mut prev = self.prev.take().unwrap();
5307 if let Some(header_offset) = &self.header_offset {
5308 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5309 }
5310 prev
5311 }
5312 #[doc = "dccp connection state\n"]
5313 pub fn push_dccp_state(mut self, value: u8) -> Self {
5314 push_header(self.as_vec_mut(), 1u16, 1 as u16);
5315 self.as_vec_mut().extend(value.to_ne_bytes());
5316 self
5317 }
5318 pub fn push_dccp_role(mut self, value: u8) -> Self {
5319 push_header(self.as_vec_mut(), 2u16, 1 as u16);
5320 self.as_vec_mut().extend(value.to_ne_bytes());
5321 self
5322 }
5323 pub fn push_dccp_handshake_seq(mut self, value: u64) -> Self {
5324 push_header(self.as_vec_mut(), 3u16, 8 as u16);
5325 self.as_vec_mut().extend(value.to_be_bytes());
5326 self
5327 }
5328 pub fn push_dccp_pad(mut self, value: &[u8]) -> Self {
5329 push_header(self.as_vec_mut(), 4u16, value.len() as u16);
5330 self.as_vec_mut().extend(value);
5331 self
5332 }
5333}
5334impl<Prev: Pusher> Drop for PushProtoinfoDccpAttrs<Prev> {
5335 fn drop(&mut self) {
5336 if let Some(prev) = &mut self.prev {
5337 if let Some(header_offset) = &self.header_offset {
5338 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5339 }
5340 }
5341 }
5342}
5343pub struct PushProtoinfoSctpAttrs<Prev: Pusher> {
5344 pub(crate) prev: Option<Prev>,
5345 pub(crate) header_offset: Option<usize>,
5346}
5347impl<Prev: Pusher> Pusher for PushProtoinfoSctpAttrs<Prev> {
5348 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5349 self.prev.as_mut().unwrap().as_vec_mut()
5350 }
5351 fn as_vec(&self) -> &Vec<u8> {
5352 self.prev.as_ref().unwrap().as_vec()
5353 }
5354}
5355impl<Prev: Pusher> PushProtoinfoSctpAttrs<Prev> {
5356 pub fn new(prev: Prev) -> Self {
5357 Self {
5358 prev: Some(prev),
5359 header_offset: None,
5360 }
5361 }
5362 pub fn end_nested(mut self) -> Prev {
5363 let mut prev = self.prev.take().unwrap();
5364 if let Some(header_offset) = &self.header_offset {
5365 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5366 }
5367 prev
5368 }
5369 #[doc = "sctp connection state\n\nAssociated type: [`NfCtSctpState`] (enum)"]
5370 pub fn push_sctp_state(mut self, value: u8) -> Self {
5371 push_header(self.as_vec_mut(), 1u16, 1 as u16);
5372 self.as_vec_mut().extend(value.to_ne_bytes());
5373 self
5374 }
5375 pub fn push_vtag_original(mut self, value: u32) -> Self {
5376 push_header(self.as_vec_mut(), 2u16, 4 as u16);
5377 self.as_vec_mut().extend(value.to_be_bytes());
5378 self
5379 }
5380 pub fn push_vtag_reply(mut self, value: u32) -> Self {
5381 push_header(self.as_vec_mut(), 3u16, 4 as u16);
5382 self.as_vec_mut().extend(value.to_be_bytes());
5383 self
5384 }
5385}
5386impl<Prev: Pusher> Drop for PushProtoinfoSctpAttrs<Prev> {
5387 fn drop(&mut self) {
5388 if let Some(prev) = &mut self.prev {
5389 if let Some(header_offset) = &self.header_offset {
5390 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5391 }
5392 }
5393 }
5394}
5395pub struct PushProtoinfoAttrs<Prev: Pusher> {
5396 pub(crate) prev: Option<Prev>,
5397 pub(crate) header_offset: Option<usize>,
5398}
5399impl<Prev: Pusher> Pusher for PushProtoinfoAttrs<Prev> {
5400 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5401 self.prev.as_mut().unwrap().as_vec_mut()
5402 }
5403 fn as_vec(&self) -> &Vec<u8> {
5404 self.prev.as_ref().unwrap().as_vec()
5405 }
5406}
5407impl<Prev: Pusher> PushProtoinfoAttrs<Prev> {
5408 pub fn new(prev: Prev) -> Self {
5409 Self {
5410 prev: Some(prev),
5411 header_offset: None,
5412 }
5413 }
5414 pub fn end_nested(mut self) -> Prev {
5415 let mut prev = self.prev.take().unwrap();
5416 if let Some(header_offset) = &self.header_offset {
5417 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5418 }
5419 prev
5420 }
5421 #[doc = "conntrack tcp state information\n"]
5422 pub fn nested_protoinfo_tcp(mut self) -> PushProtoinfoTcpAttrs<Self> {
5423 let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
5424 PushProtoinfoTcpAttrs {
5425 prev: Some(self),
5426 header_offset: Some(header_offset),
5427 }
5428 }
5429 #[doc = "conntrack dccp state information\n"]
5430 pub fn nested_protoinfo_dccp(mut self) -> PushProtoinfoDccpAttrs<Self> {
5431 let header_offset = push_nested_header(self.as_vec_mut(), 2u16);
5432 PushProtoinfoDccpAttrs {
5433 prev: Some(self),
5434 header_offset: Some(header_offset),
5435 }
5436 }
5437 #[doc = "conntrack sctp state information\n"]
5438 pub fn nested_protoinfo_sctp(mut self) -> PushProtoinfoSctpAttrs<Self> {
5439 let header_offset = push_nested_header(self.as_vec_mut(), 3u16);
5440 PushProtoinfoSctpAttrs {
5441 prev: Some(self),
5442 header_offset: Some(header_offset),
5443 }
5444 }
5445}
5446impl<Prev: Pusher> Drop for PushProtoinfoAttrs<Prev> {
5447 fn drop(&mut self) {
5448 if let Some(prev) = &mut self.prev {
5449 if let Some(header_offset) = &self.header_offset {
5450 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5451 }
5452 }
5453 }
5454}
5455pub struct PushHelpAttrs<Prev: Pusher> {
5456 pub(crate) prev: Option<Prev>,
5457 pub(crate) header_offset: Option<usize>,
5458}
5459impl<Prev: Pusher> Pusher for PushHelpAttrs<Prev> {
5460 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5461 self.prev.as_mut().unwrap().as_vec_mut()
5462 }
5463 fn as_vec(&self) -> &Vec<u8> {
5464 self.prev.as_ref().unwrap().as_vec()
5465 }
5466}
5467impl<Prev: Pusher> PushHelpAttrs<Prev> {
5468 pub fn new(prev: Prev) -> Self {
5469 Self {
5470 prev: Some(prev),
5471 header_offset: None,
5472 }
5473 }
5474 pub fn end_nested(mut self) -> Prev {
5475 let mut prev = self.prev.take().unwrap();
5476 if let Some(header_offset) = &self.header_offset {
5477 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5478 }
5479 prev
5480 }
5481 #[doc = "helper name\n"]
5482 pub fn push_help_name(mut self, value: &CStr) -> Self {
5483 push_header(
5484 self.as_vec_mut(),
5485 1u16,
5486 value.to_bytes_with_nul().len() as u16,
5487 );
5488 self.as_vec_mut().extend(value.to_bytes_with_nul());
5489 self
5490 }
5491 #[doc = "helper name\n"]
5492 pub fn push_help_name_bytes(mut self, value: &[u8]) -> Self {
5493 push_header(self.as_vec_mut(), 1u16, (value.len() + 1) as u16);
5494 self.as_vec_mut().extend(value);
5495 self.as_vec_mut().push(0);
5496 self
5497 }
5498}
5499impl<Prev: Pusher> Drop for PushHelpAttrs<Prev> {
5500 fn drop(&mut self) {
5501 if let Some(prev) = &mut self.prev {
5502 if let Some(header_offset) = &self.header_offset {
5503 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5504 }
5505 }
5506 }
5507}
5508pub struct PushNatProtoAttrs<Prev: Pusher> {
5509 pub(crate) prev: Option<Prev>,
5510 pub(crate) header_offset: Option<usize>,
5511}
5512impl<Prev: Pusher> Pusher for PushNatProtoAttrs<Prev> {
5513 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5514 self.prev.as_mut().unwrap().as_vec_mut()
5515 }
5516 fn as_vec(&self) -> &Vec<u8> {
5517 self.prev.as_ref().unwrap().as_vec()
5518 }
5519}
5520impl<Prev: Pusher> PushNatProtoAttrs<Prev> {
5521 pub fn new(prev: Prev) -> Self {
5522 Self {
5523 prev: Some(prev),
5524 header_offset: None,
5525 }
5526 }
5527 pub fn end_nested(mut self) -> Prev {
5528 let mut prev = self.prev.take().unwrap();
5529 if let Some(header_offset) = &self.header_offset {
5530 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5531 }
5532 prev
5533 }
5534 pub fn push_nat_port_min(mut self, value: u16) -> Self {
5535 push_header(self.as_vec_mut(), 1u16, 2 as u16);
5536 self.as_vec_mut().extend(value.to_be_bytes());
5537 self
5538 }
5539 pub fn push_nat_port_max(mut self, value: u16) -> Self {
5540 push_header(self.as_vec_mut(), 2u16, 2 as u16);
5541 self.as_vec_mut().extend(value.to_be_bytes());
5542 self
5543 }
5544}
5545impl<Prev: Pusher> Drop for PushNatProtoAttrs<Prev> {
5546 fn drop(&mut self) {
5547 if let Some(prev) = &mut self.prev {
5548 if let Some(header_offset) = &self.header_offset {
5549 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5550 }
5551 }
5552 }
5553}
5554pub struct PushNatAttrs<Prev: Pusher> {
5555 pub(crate) prev: Option<Prev>,
5556 pub(crate) header_offset: Option<usize>,
5557}
5558impl<Prev: Pusher> Pusher for PushNatAttrs<Prev> {
5559 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5560 self.prev.as_mut().unwrap().as_vec_mut()
5561 }
5562 fn as_vec(&self) -> &Vec<u8> {
5563 self.prev.as_ref().unwrap().as_vec()
5564 }
5565}
5566impl<Prev: Pusher> PushNatAttrs<Prev> {
5567 pub fn new(prev: Prev) -> Self {
5568 Self {
5569 prev: Some(prev),
5570 header_offset: None,
5571 }
5572 }
5573 pub fn end_nested(mut self) -> Prev {
5574 let mut prev = self.prev.take().unwrap();
5575 if let Some(header_offset) = &self.header_offset {
5576 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5577 }
5578 prev
5579 }
5580 pub fn push_nat_v4_minip(mut self, value: u32) -> Self {
5581 push_header(self.as_vec_mut(), 1u16, 4 as u16);
5582 self.as_vec_mut().extend(value.to_be_bytes());
5583 self
5584 }
5585 pub fn push_nat_v4_maxip(mut self, value: u32) -> Self {
5586 push_header(self.as_vec_mut(), 2u16, 4 as u16);
5587 self.as_vec_mut().extend(value.to_be_bytes());
5588 self
5589 }
5590 pub fn push_nat_v6_minip(mut self, value: &[u8]) -> Self {
5591 push_header(self.as_vec_mut(), 3u16, value.len() as u16);
5592 self.as_vec_mut().extend(value);
5593 self
5594 }
5595 pub fn push_nat_v6_maxip(mut self, value: &[u8]) -> Self {
5596 push_header(self.as_vec_mut(), 4u16, value.len() as u16);
5597 self.as_vec_mut().extend(value);
5598 self
5599 }
5600 pub fn nested_nat_proto(mut self) -> PushNatProtoAttrs<Self> {
5601 let header_offset = push_nested_header(self.as_vec_mut(), 5u16);
5602 PushNatProtoAttrs {
5603 prev: Some(self),
5604 header_offset: Some(header_offset),
5605 }
5606 }
5607}
5608impl<Prev: Pusher> Drop for PushNatAttrs<Prev> {
5609 fn drop(&mut self) {
5610 if let Some(prev) = &mut self.prev {
5611 if let Some(header_offset) = &self.header_offset {
5612 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5613 }
5614 }
5615 }
5616}
5617pub struct PushSeqadjAttrs<Prev: Pusher> {
5618 pub(crate) prev: Option<Prev>,
5619 pub(crate) header_offset: Option<usize>,
5620}
5621impl<Prev: Pusher> Pusher for PushSeqadjAttrs<Prev> {
5622 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5623 self.prev.as_mut().unwrap().as_vec_mut()
5624 }
5625 fn as_vec(&self) -> &Vec<u8> {
5626 self.prev.as_ref().unwrap().as_vec()
5627 }
5628}
5629impl<Prev: Pusher> PushSeqadjAttrs<Prev> {
5630 pub fn new(prev: Prev) -> Self {
5631 Self {
5632 prev: Some(prev),
5633 header_offset: None,
5634 }
5635 }
5636 pub fn end_nested(mut self) -> Prev {
5637 let mut prev = self.prev.take().unwrap();
5638 if let Some(header_offset) = &self.header_offset {
5639 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5640 }
5641 prev
5642 }
5643 pub fn push_correction_pos(mut self, value: u32) -> Self {
5644 push_header(self.as_vec_mut(), 1u16, 4 as u16);
5645 self.as_vec_mut().extend(value.to_be_bytes());
5646 self
5647 }
5648 pub fn push_offset_before(mut self, value: u32) -> Self {
5649 push_header(self.as_vec_mut(), 2u16, 4 as u16);
5650 self.as_vec_mut().extend(value.to_be_bytes());
5651 self
5652 }
5653 pub fn push_offset_after(mut self, value: u32) -> Self {
5654 push_header(self.as_vec_mut(), 3u16, 4 as u16);
5655 self.as_vec_mut().extend(value.to_be_bytes());
5656 self
5657 }
5658}
5659impl<Prev: Pusher> Drop for PushSeqadjAttrs<Prev> {
5660 fn drop(&mut self) {
5661 if let Some(prev) = &mut self.prev {
5662 if let Some(header_offset) = &self.header_offset {
5663 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5664 }
5665 }
5666 }
5667}
5668pub struct PushSecctxAttrs<Prev: Pusher> {
5669 pub(crate) prev: Option<Prev>,
5670 pub(crate) header_offset: Option<usize>,
5671}
5672impl<Prev: Pusher> Pusher for PushSecctxAttrs<Prev> {
5673 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5674 self.prev.as_mut().unwrap().as_vec_mut()
5675 }
5676 fn as_vec(&self) -> &Vec<u8> {
5677 self.prev.as_ref().unwrap().as_vec()
5678 }
5679}
5680impl<Prev: Pusher> PushSecctxAttrs<Prev> {
5681 pub fn new(prev: Prev) -> Self {
5682 Self {
5683 prev: Some(prev),
5684 header_offset: None,
5685 }
5686 }
5687 pub fn end_nested(mut self) -> Prev {
5688 let mut prev = self.prev.take().unwrap();
5689 if let Some(header_offset) = &self.header_offset {
5690 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5691 }
5692 prev
5693 }
5694 pub fn push_secctx_name(mut self, value: &CStr) -> Self {
5695 push_header(
5696 self.as_vec_mut(),
5697 1u16,
5698 value.to_bytes_with_nul().len() as u16,
5699 );
5700 self.as_vec_mut().extend(value.to_bytes_with_nul());
5701 self
5702 }
5703 pub fn push_secctx_name_bytes(mut self, value: &[u8]) -> Self {
5704 push_header(self.as_vec_mut(), 1u16, (value.len() + 1) as u16);
5705 self.as_vec_mut().extend(value);
5706 self.as_vec_mut().push(0);
5707 self
5708 }
5709}
5710impl<Prev: Pusher> Drop for PushSecctxAttrs<Prev> {
5711 fn drop(&mut self) {
5712 if let Some(prev) = &mut self.prev {
5713 if let Some(header_offset) = &self.header_offset {
5714 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5715 }
5716 }
5717 }
5718}
5719pub struct PushSynproxyAttrs<Prev: Pusher> {
5720 pub(crate) prev: Option<Prev>,
5721 pub(crate) header_offset: Option<usize>,
5722}
5723impl<Prev: Pusher> Pusher for PushSynproxyAttrs<Prev> {
5724 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5725 self.prev.as_mut().unwrap().as_vec_mut()
5726 }
5727 fn as_vec(&self) -> &Vec<u8> {
5728 self.prev.as_ref().unwrap().as_vec()
5729 }
5730}
5731impl<Prev: Pusher> PushSynproxyAttrs<Prev> {
5732 pub fn new(prev: Prev) -> Self {
5733 Self {
5734 prev: Some(prev),
5735 header_offset: None,
5736 }
5737 }
5738 pub fn end_nested(mut self) -> Prev {
5739 let mut prev = self.prev.take().unwrap();
5740 if let Some(header_offset) = &self.header_offset {
5741 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5742 }
5743 prev
5744 }
5745 pub fn push_isn(mut self, value: u32) -> Self {
5746 push_header(self.as_vec_mut(), 1u16, 4 as u16);
5747 self.as_vec_mut().extend(value.to_be_bytes());
5748 self
5749 }
5750 pub fn push_its(mut self, value: u32) -> Self {
5751 push_header(self.as_vec_mut(), 2u16, 4 as u16);
5752 self.as_vec_mut().extend(value.to_be_bytes());
5753 self
5754 }
5755 pub fn push_tsoff(mut self, value: u32) -> Self {
5756 push_header(self.as_vec_mut(), 3u16, 4 as u16);
5757 self.as_vec_mut().extend(value.to_be_bytes());
5758 self
5759 }
5760}
5761impl<Prev: Pusher> Drop for PushSynproxyAttrs<Prev> {
5762 fn drop(&mut self) {
5763 if let Some(prev) = &mut self.prev {
5764 if let Some(header_offset) = &self.header_offset {
5765 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5766 }
5767 }
5768 }
5769}
5770pub struct PushConntrackAttrs<Prev: Pusher> {
5771 pub(crate) prev: Option<Prev>,
5772 pub(crate) header_offset: Option<usize>,
5773}
5774impl<Prev: Pusher> Pusher for PushConntrackAttrs<Prev> {
5775 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5776 self.prev.as_mut().unwrap().as_vec_mut()
5777 }
5778 fn as_vec(&self) -> &Vec<u8> {
5779 self.prev.as_ref().unwrap().as_vec()
5780 }
5781}
5782impl<Prev: Pusher> PushConntrackAttrs<Prev> {
5783 pub fn new(prev: Prev) -> Self {
5784 Self {
5785 prev: Some(prev),
5786 header_offset: None,
5787 }
5788 }
5789 pub fn end_nested(mut self) -> Prev {
5790 let mut prev = self.prev.take().unwrap();
5791 if let Some(header_offset) = &self.header_offset {
5792 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5793 }
5794 prev
5795 }
5796 #[doc = "conntrack l3+l4 protocol information, original direction\n"]
5797 pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
5798 let header_offset = push_nested_header(self.as_vec_mut(), 1u16);
5799 PushTupleAttrs {
5800 prev: Some(self),
5801 header_offset: Some(header_offset),
5802 }
5803 }
5804 #[doc = "conntrack l3+l4 protocol information, reply direction\n"]
5805 pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
5806 let header_offset = push_nested_header(self.as_vec_mut(), 2u16);
5807 PushTupleAttrs {
5808 prev: Some(self),
5809 header_offset: Some(header_offset),
5810 }
5811 }
5812 #[doc = "conntrack flag bits\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
5813 pub fn push_status(mut self, value: u32) -> Self {
5814 push_header(self.as_vec_mut(), 3u16, 4 as u16);
5815 self.as_vec_mut().extend(value.to_be_bytes());
5816 self
5817 }
5818 pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
5819 let header_offset = push_nested_header(self.as_vec_mut(), 4u16);
5820 PushProtoinfoAttrs {
5821 prev: Some(self),
5822 header_offset: Some(header_offset),
5823 }
5824 }
5825 pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
5826 let header_offset = push_nested_header(self.as_vec_mut(), 5u16);
5827 PushHelpAttrs {
5828 prev: Some(self),
5829 header_offset: Some(header_offset),
5830 }
5831 }
5832 pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
5833 let header_offset = push_nested_header(self.as_vec_mut(), 6u16);
5834 PushNatAttrs {
5835 prev: Some(self),
5836 header_offset: Some(header_offset),
5837 }
5838 }
5839 pub fn push_timeout(mut self, value: u32) -> Self {
5840 push_header(self.as_vec_mut(), 7u16, 4 as u16);
5841 self.as_vec_mut().extend(value.to_be_bytes());
5842 self
5843 }
5844 pub fn push_mark(mut self, value: u32) -> Self {
5845 push_header(self.as_vec_mut(), 8u16, 4 as u16);
5846 self.as_vec_mut().extend(value.to_be_bytes());
5847 self
5848 }
5849 pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
5850 let header_offset = push_nested_header(self.as_vec_mut(), 9u16);
5851 PushCounterAttrs {
5852 prev: Some(self),
5853 header_offset: Some(header_offset),
5854 }
5855 }
5856 pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
5857 let header_offset = push_nested_header(self.as_vec_mut(), 10u16);
5858 PushCounterAttrs {
5859 prev: Some(self),
5860 header_offset: Some(header_offset),
5861 }
5862 }
5863 pub fn push_use(mut self, value: u32) -> Self {
5864 push_header(self.as_vec_mut(), 11u16, 4 as u16);
5865 self.as_vec_mut().extend(value.to_be_bytes());
5866 self
5867 }
5868 pub fn push_id(mut self, value: u32) -> Self {
5869 push_header(self.as_vec_mut(), 12u16, 4 as u16);
5870 self.as_vec_mut().extend(value.to_be_bytes());
5871 self
5872 }
5873 pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
5874 let header_offset = push_nested_header(self.as_vec_mut(), 13u16);
5875 PushNatAttrs {
5876 prev: Some(self),
5877 header_offset: Some(header_offset),
5878 }
5879 }
5880 pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
5881 let header_offset = push_nested_header(self.as_vec_mut(), 14u16);
5882 PushTupleAttrs {
5883 prev: Some(self),
5884 header_offset: Some(header_offset),
5885 }
5886 }
5887 pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
5888 let header_offset = push_nested_header(self.as_vec_mut(), 15u16);
5889 PushSeqadjAttrs {
5890 prev: Some(self),
5891 header_offset: Some(header_offset),
5892 }
5893 }
5894 pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
5895 let header_offset = push_nested_header(self.as_vec_mut(), 16u16);
5896 PushSeqadjAttrs {
5897 prev: Some(self),
5898 header_offset: Some(header_offset),
5899 }
5900 }
5901 #[doc = "obsolete\n"]
5902 pub fn push_secmark(mut self, value: &[u8]) -> Self {
5903 push_header(self.as_vec_mut(), 17u16, value.len() as u16);
5904 self.as_vec_mut().extend(value);
5905 self
5906 }
5907 #[doc = "conntrack zone id\n"]
5908 pub fn push_zone(mut self, value: u16) -> Self {
5909 push_header(self.as_vec_mut(), 18u16, 2 as u16);
5910 self.as_vec_mut().extend(value.to_be_bytes());
5911 self
5912 }
5913 pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
5914 let header_offset = push_nested_header(self.as_vec_mut(), 19u16);
5915 PushSecctxAttrs {
5916 prev: Some(self),
5917 header_offset: Some(header_offset),
5918 }
5919 }
5920 pub fn push_timestamp(mut self, value: u64) -> Self {
5921 push_header(self.as_vec_mut(), 20u16, 8 as u16);
5922 self.as_vec_mut().extend(value.to_be_bytes());
5923 self
5924 }
5925 pub fn push_mark_mask(mut self, value: u32) -> Self {
5926 push_header(self.as_vec_mut(), 21u16, 4 as u16);
5927 self.as_vec_mut().extend(value.to_be_bytes());
5928 self
5929 }
5930 pub fn push_labels(mut self, value: &[u8]) -> Self {
5931 push_header(self.as_vec_mut(), 22u16, value.len() as u16);
5932 self.as_vec_mut().extend(value);
5933 self
5934 }
5935 pub fn push_labels_mask(mut self, value: &[u8]) -> Self {
5936 push_header(self.as_vec_mut(), 23u16, value.len() as u16);
5937 self.as_vec_mut().extend(value);
5938 self
5939 }
5940 pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
5941 let header_offset = push_nested_header(self.as_vec_mut(), 24u16);
5942 PushSynproxyAttrs {
5943 prev: Some(self),
5944 header_offset: Some(header_offset),
5945 }
5946 }
5947 pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
5948 let header_offset = push_nested_header(self.as_vec_mut(), 25u16);
5949 PushTupleAttrs {
5950 prev: Some(self),
5951 header_offset: Some(header_offset),
5952 }
5953 }
5954 #[doc = "conntrack flag bits to change\n\nAssociated type: [`NfCtStatus`] (1 bit per enumeration)"]
5955 pub fn push_status_mask(mut self, value: u32) -> Self {
5956 push_header(self.as_vec_mut(), 26u16, 4 as u16);
5957 self.as_vec_mut().extend(value.to_be_bytes());
5958 self
5959 }
5960 pub fn push_timestamp_event(mut self, value: u64) -> Self {
5961 push_header(self.as_vec_mut(), 27u16, 8 as u16);
5962 self.as_vec_mut().extend(value.to_be_bytes());
5963 self
5964 }
5965}
5966impl<Prev: Pusher> Drop for PushConntrackAttrs<Prev> {
5967 fn drop(&mut self) {
5968 if let Some(prev) = &mut self.prev {
5969 if let Some(header_offset) = &self.header_offset {
5970 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5971 }
5972 }
5973 }
5974}
5975pub struct PushConntrackStatsAttrs<Prev: Pusher> {
5976 pub(crate) prev: Option<Prev>,
5977 pub(crate) header_offset: Option<usize>,
5978}
5979impl<Prev: Pusher> Pusher for PushConntrackStatsAttrs<Prev> {
5980 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
5981 self.prev.as_mut().unwrap().as_vec_mut()
5982 }
5983 fn as_vec(&self) -> &Vec<u8> {
5984 self.prev.as_ref().unwrap().as_vec()
5985 }
5986}
5987impl<Prev: Pusher> PushConntrackStatsAttrs<Prev> {
5988 pub fn new(prev: Prev) -> Self {
5989 Self {
5990 prev: Some(prev),
5991 header_offset: None,
5992 }
5993 }
5994 pub fn end_nested(mut self) -> Prev {
5995 let mut prev = self.prev.take().unwrap();
5996 if let Some(header_offset) = &self.header_offset {
5997 finalize_nested_header(prev.as_vec_mut(), *header_offset);
5998 }
5999 prev
6000 }
6001 #[doc = "obsolete\n"]
6002 pub fn push_searched(mut self, value: u32) -> Self {
6003 push_header(self.as_vec_mut(), 1u16, 4 as u16);
6004 self.as_vec_mut().extend(value.to_be_bytes());
6005 self
6006 }
6007 pub fn push_found(mut self, value: u32) -> Self {
6008 push_header(self.as_vec_mut(), 2u16, 4 as u16);
6009 self.as_vec_mut().extend(value.to_be_bytes());
6010 self
6011 }
6012 #[doc = "obsolete\n"]
6013 pub fn push_new(mut self, value: u32) -> Self {
6014 push_header(self.as_vec_mut(), 3u16, 4 as u16);
6015 self.as_vec_mut().extend(value.to_be_bytes());
6016 self
6017 }
6018 #[doc = "obsolete\n"]
6019 pub fn push_invalid(mut self, value: u32) -> Self {
6020 push_header(self.as_vec_mut(), 4u16, 4 as u16);
6021 self.as_vec_mut().extend(value.to_be_bytes());
6022 self
6023 }
6024 #[doc = "obsolete\n"]
6025 pub fn push_ignore(mut self, value: u32) -> Self {
6026 push_header(self.as_vec_mut(), 5u16, 4 as u16);
6027 self.as_vec_mut().extend(value.to_be_bytes());
6028 self
6029 }
6030 #[doc = "obsolete\n"]
6031 pub fn push_delete(mut self, value: u32) -> Self {
6032 push_header(self.as_vec_mut(), 6u16, 4 as u16);
6033 self.as_vec_mut().extend(value.to_be_bytes());
6034 self
6035 }
6036 #[doc = "obsolete\n"]
6037 pub fn push_delete_list(mut self, value: u32) -> Self {
6038 push_header(self.as_vec_mut(), 7u16, 4 as u16);
6039 self.as_vec_mut().extend(value.to_be_bytes());
6040 self
6041 }
6042 pub fn push_insert(mut self, value: u32) -> Self {
6043 push_header(self.as_vec_mut(), 8u16, 4 as u16);
6044 self.as_vec_mut().extend(value.to_be_bytes());
6045 self
6046 }
6047 pub fn push_insert_failed(mut self, value: u32) -> Self {
6048 push_header(self.as_vec_mut(), 9u16, 4 as u16);
6049 self.as_vec_mut().extend(value.to_be_bytes());
6050 self
6051 }
6052 pub fn push_drop(mut self, value: u32) -> Self {
6053 push_header(self.as_vec_mut(), 10u16, 4 as u16);
6054 self.as_vec_mut().extend(value.to_be_bytes());
6055 self
6056 }
6057 pub fn push_early_drop(mut self, value: u32) -> Self {
6058 push_header(self.as_vec_mut(), 11u16, 4 as u16);
6059 self.as_vec_mut().extend(value.to_be_bytes());
6060 self
6061 }
6062 pub fn push_error(mut self, value: u32) -> Self {
6063 push_header(self.as_vec_mut(), 12u16, 4 as u16);
6064 self.as_vec_mut().extend(value.to_be_bytes());
6065 self
6066 }
6067 pub fn push_search_restart(mut self, value: u32) -> Self {
6068 push_header(self.as_vec_mut(), 13u16, 4 as u16);
6069 self.as_vec_mut().extend(value.to_be_bytes());
6070 self
6071 }
6072 pub fn push_clash_resolve(mut self, value: u32) -> Self {
6073 push_header(self.as_vec_mut(), 14u16, 4 as u16);
6074 self.as_vec_mut().extend(value.to_be_bytes());
6075 self
6076 }
6077 pub fn push_chain_toolong(mut self, value: u32) -> Self {
6078 push_header(self.as_vec_mut(), 15u16, 4 as u16);
6079 self.as_vec_mut().extend(value.to_be_bytes());
6080 self
6081 }
6082}
6083impl<Prev: Pusher> Drop for PushConntrackStatsAttrs<Prev> {
6084 fn drop(&mut self) {
6085 if let Some(prev) = &mut self.prev {
6086 if let Some(header_offset) = &self.header_offset {
6087 finalize_nested_header(prev.as_vec_mut(), *header_offset);
6088 }
6089 }
6090 }
6091}
6092#[doc = "get / dump entries\n\nRequest attributes:\n- [.push_status()](PushConntrackAttrs::push_status)\n- [.push_mark()](PushConntrackAttrs::push_mark)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n- [.nested_filter()](PushConntrackAttrs::nested_filter)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n\n"]
6093#[derive(Debug)]
6094pub struct OpGetDump<'r> {
6095 request: Request<'r>,
6096}
6097impl<'r> OpGetDump<'r> {
6098 pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6099 Self::write_header(request.buf_mut(), header);
6100 Self {
6101 request: request.set_dump(),
6102 }
6103 }
6104 pub fn encode_request<'buf>(
6105 buf: &'buf mut Vec<u8>,
6106 header: &Nfgenmsg,
6107 ) -> PushConntrackAttrs<&'buf mut Vec<u8>> {
6108 Self::write_header(buf, header);
6109 PushConntrackAttrs::new(buf)
6110 }
6111 pub fn encode(&mut self) -> PushConntrackAttrs<&mut Vec<u8>> {
6112 PushConntrackAttrs::new(self.request.buf_mut())
6113 }
6114 pub fn into_encoder(self) -> PushConntrackAttrs<RequestBuf<'r>> {
6115 PushConntrackAttrs::new(self.request.buf)
6116 }
6117 pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackAttrs<'a>) {
6118 let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6119 (
6120 Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6121 IterableConntrackAttrs::with_loc(attrs, buf.as_ptr() as usize),
6122 )
6123 }
6124 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Nfgenmsg) {
6125 prev.as_vec_mut().extend(header.as_slice());
6126 }
6127}
6128impl NetlinkRequest for OpGetDump<'_> {
6129 fn protocol(&self) -> Protocol {
6130 Protocol::Raw {
6131 protonum: 12u16,
6132 request_type: 257u16,
6133 }
6134 }
6135 fn flags(&self) -> u16 {
6136 self.request.flags
6137 }
6138 fn payload(&self) -> &[u8] {
6139 self.request.buf()
6140 }
6141 type ReplyType<'buf> = (Nfgenmsg, IterableConntrackAttrs<'buf>);
6142 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6143 Self::decode_request(buf)
6144 }
6145 fn lookup(
6146 buf: &[u8],
6147 offset: usize,
6148 missing_type: Option<u16>,
6149 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6150 Self::decode_request(buf)
6151 .1
6152 .lookup_attr(offset, missing_type)
6153 }
6154}
6155#[doc = "get / dump entries\n\nRequest attributes:\n- [.nested_tuple_orig()](PushConntrackAttrs::nested_tuple_orig)\n- [.nested_tuple_reply()](PushConntrackAttrs::nested_tuple_reply)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n\n"]
6156#[derive(Debug)]
6157pub struct OpGetDo<'r> {
6158 request: Request<'r>,
6159}
6160impl<'r> OpGetDo<'r> {
6161 pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6162 Self::write_header(request.buf_mut(), header);
6163 Self { request: request }
6164 }
6165 pub fn encode_request<'buf>(
6166 buf: &'buf mut Vec<u8>,
6167 header: &Nfgenmsg,
6168 ) -> PushConntrackAttrs<&'buf mut Vec<u8>> {
6169 Self::write_header(buf, header);
6170 PushConntrackAttrs::new(buf)
6171 }
6172 pub fn encode(&mut self) -> PushConntrackAttrs<&mut Vec<u8>> {
6173 PushConntrackAttrs::new(self.request.buf_mut())
6174 }
6175 pub fn into_encoder(self) -> PushConntrackAttrs<RequestBuf<'r>> {
6176 PushConntrackAttrs::new(self.request.buf)
6177 }
6178 pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackAttrs<'a>) {
6179 let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6180 (
6181 Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6182 IterableConntrackAttrs::with_loc(attrs, buf.as_ptr() as usize),
6183 )
6184 }
6185 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Nfgenmsg) {
6186 prev.as_vec_mut().extend(header.as_slice());
6187 }
6188}
6189impl NetlinkRequest for OpGetDo<'_> {
6190 fn protocol(&self) -> Protocol {
6191 Protocol::Raw {
6192 protonum: 12u16,
6193 request_type: 257u16,
6194 }
6195 }
6196 fn flags(&self) -> u16 {
6197 self.request.flags
6198 }
6199 fn payload(&self) -> &[u8] {
6200 self.request.buf()
6201 }
6202 type ReplyType<'buf> = (Nfgenmsg, IterableConntrackAttrs<'buf>);
6203 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6204 Self::decode_request(buf)
6205 }
6206 fn lookup(
6207 buf: &[u8],
6208 offset: usize,
6209 missing_type: Option<u16>,
6210 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6211 Self::decode_request(buf)
6212 .1
6213 .lookup_attr(offset, missing_type)
6214 }
6215}
6216#[doc = "dump pcpu conntrack stats\n\nReply attributes:\n- [.get_searched()](IterableConntrackStatsAttrs::get_searched)\n- [.get_found()](IterableConntrackStatsAttrs::get_found)\n- [.get_insert()](IterableConntrackStatsAttrs::get_insert)\n- [.get_insert_failed()](IterableConntrackStatsAttrs::get_insert_failed)\n- [.get_drop()](IterableConntrackStatsAttrs::get_drop)\n- [.get_early_drop()](IterableConntrackStatsAttrs::get_early_drop)\n- [.get_error()](IterableConntrackStatsAttrs::get_error)\n- [.get_search_restart()](IterableConntrackStatsAttrs::get_search_restart)\n- [.get_clash_resolve()](IterableConntrackStatsAttrs::get_clash_resolve)\n- [.get_chain_toolong()](IterableConntrackStatsAttrs::get_chain_toolong)\n\n"]
6217#[derive(Debug)]
6218pub struct OpGetStatsDump<'r> {
6219 request: Request<'r>,
6220}
6221impl<'r> OpGetStatsDump<'r> {
6222 pub fn new(mut request: Request<'r>, header: &Nfgenmsg) -> Self {
6223 Self::write_header(request.buf_mut(), header);
6224 Self {
6225 request: request.set_dump(),
6226 }
6227 }
6228 pub fn encode_request<'buf>(
6229 buf: &'buf mut Vec<u8>,
6230 header: &Nfgenmsg,
6231 ) -> PushConntrackStatsAttrs<&'buf mut Vec<u8>> {
6232 Self::write_header(buf, header);
6233 PushConntrackStatsAttrs::new(buf)
6234 }
6235 pub fn encode(&mut self) -> PushConntrackStatsAttrs<&mut Vec<u8>> {
6236 PushConntrackStatsAttrs::new(self.request.buf_mut())
6237 }
6238 pub fn into_encoder(self) -> PushConntrackStatsAttrs<RequestBuf<'r>> {
6239 PushConntrackStatsAttrs::new(self.request.buf)
6240 }
6241 pub fn decode_request<'a>(buf: &'a [u8]) -> (Nfgenmsg, IterableConntrackStatsAttrs<'a>) {
6242 let (header, attrs) = buf.split_at(buf.len().min(Nfgenmsg::len()));
6243 (
6244 Nfgenmsg::new_from_slice(header).unwrap_or_default(),
6245 IterableConntrackStatsAttrs::with_loc(attrs, buf.as_ptr() as usize),
6246 )
6247 }
6248 fn write_header<Prev: Pusher>(prev: &mut Prev, header: &Nfgenmsg) {
6249 prev.as_vec_mut().extend(header.as_slice());
6250 }
6251}
6252impl NetlinkRequest for OpGetStatsDump<'_> {
6253 fn protocol(&self) -> Protocol {
6254 Protocol::Raw {
6255 protonum: 12u16,
6256 request_type: 260u16,
6257 }
6258 }
6259 fn flags(&self) -> u16 {
6260 self.request.flags
6261 }
6262 fn payload(&self) -> &[u8] {
6263 self.request.buf()
6264 }
6265 type ReplyType<'buf> = (Nfgenmsg, IterableConntrackStatsAttrs<'buf>);
6266 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6267 Self::decode_request(buf)
6268 }
6269 fn lookup(
6270 buf: &[u8],
6271 offset: usize,
6272 missing_type: Option<u16>,
6273 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6274 Self::decode_request(buf)
6275 .1
6276 .lookup_attr(offset, missing_type)
6277 }
6278}
6279#[derive(Debug)]
6280pub struct ChainedFinal<'a> {
6281 inner: Chained<'a>,
6282}
6283#[derive(Debug)]
6284pub struct Chained<'a> {
6285 buf: RequestBuf<'a>,
6286 first_seq: u32,
6287 lookups: Vec<(&'static str, LookupFn)>,
6288 last_header_offset: usize,
6289 last_kind: Option<RequestInfo>,
6290}
6291impl<'a> ChainedFinal<'a> {
6292 pub fn into_chained(self) -> Chained<'a> {
6293 self.inner
6294 }
6295 pub fn buf(&self) -> &Vec<u8> {
6296 self.inner.buf()
6297 }
6298 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6299 self.inner.buf_mut()
6300 }
6301 fn get_index(&self, seq: u32) -> Option<u32> {
6302 let min = self.inner.first_seq;
6303 let max = min.wrapping_add(self.inner.lookups.len() as u32);
6304 return if min <= max {
6305 (min..max).contains(&seq).then(|| seq - min)
6306 } else if min <= seq {
6307 Some(seq - min)
6308 } else if seq < max {
6309 Some(u32::MAX - min + seq)
6310 } else {
6311 None
6312 };
6313 }
6314}
6315impl crate::traits::NetlinkChained for ChainedFinal<'_> {
6316 fn protonum(&self) -> u16 {
6317 PROTONUM
6318 }
6319 fn payload(&self) -> &[u8] {
6320 self.buf()
6321 }
6322 fn chain_len(&self) -> usize {
6323 self.inner.lookups.len()
6324 }
6325 fn get_index(&self, seq: u32) -> Option<usize> {
6326 self.get_index(seq).map(|n| n as usize)
6327 }
6328 fn name(&self, index: usize) -> &'static str {
6329 self.inner.lookups[index].0
6330 }
6331 fn lookup(&self, index: usize) -> LookupFn {
6332 self.inner.lookups[index].1
6333 }
6334}
6335impl Chained<'static> {
6336 pub fn new(first_seq: u32) -> Self {
6337 Self::new_from_buf(Vec::new(), first_seq)
6338 }
6339 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
6340 Self {
6341 buf: RequestBuf::Own(buf),
6342 first_seq,
6343 lookups: Vec::new(),
6344 last_header_offset: 0,
6345 last_kind: None,
6346 }
6347 }
6348 pub fn into_buf(self) -> Vec<u8> {
6349 match self.buf {
6350 RequestBuf::Own(buf) => buf,
6351 _ => unreachable!(),
6352 }
6353 }
6354}
6355impl<'a> Chained<'a> {
6356 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
6357 Self {
6358 buf: RequestBuf::Ref(buf),
6359 first_seq,
6360 lookups: Vec::new(),
6361 last_header_offset: 0,
6362 last_kind: None,
6363 }
6364 }
6365 pub fn finalize(mut self) -> ChainedFinal<'a> {
6366 self.update_header();
6367 ChainedFinal { inner: self }
6368 }
6369 pub fn request(&mut self) -> Request<'_> {
6370 self.update_header();
6371 self.last_header_offset = self.buf().len();
6372 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
6373 let mut request = Request::new_extend(self.buf.buf_mut());
6374 self.last_kind = None;
6375 request.writeback = Some(&mut self.last_kind);
6376 request
6377 }
6378 pub fn buf(&self) -> &Vec<u8> {
6379 self.buf.buf()
6380 }
6381 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6382 self.buf.buf_mut()
6383 }
6384 fn update_header(&mut self) {
6385 let Some(RequestInfo {
6386 protocol,
6387 flags,
6388 name,
6389 lookup,
6390 }) = self.last_kind
6391 else {
6392 if !self.buf().is_empty() {
6393 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
6394 self.buf.buf_mut().truncate(self.last_header_offset);
6395 }
6396 return;
6397 };
6398 let header_offset = self.last_header_offset;
6399 let request_type = match protocol {
6400 Protocol::Raw { request_type, .. } => request_type,
6401 Protocol::Generic(_) => unreachable!(),
6402 };
6403 let index = self.lookups.len();
6404 let seq = self.first_seq.wrapping_add(index as u32);
6405 self.lookups.push((name, lookup));
6406 let buf = self.buf_mut();
6407 align(buf);
6408 let header = Nlmsghdr {
6409 len: (buf.len() - header_offset) as u32,
6410 r#type: request_type,
6411 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
6412 seq,
6413 pid: 0,
6414 };
6415 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
6416 }
6417}
6418use crate::traits::LookupFn;
6419use crate::utils::RequestBuf;
6420#[derive(Debug)]
6421pub struct Request<'buf> {
6422 buf: RequestBuf<'buf>,
6423 flags: u16,
6424 writeback: Option<&'buf mut Option<RequestInfo>>,
6425}
6426#[allow(unused)]
6427#[derive(Debug, Clone)]
6428pub struct RequestInfo {
6429 protocol: Protocol,
6430 flags: u16,
6431 name: &'static str,
6432 lookup: LookupFn,
6433}
6434impl Request<'static> {
6435 pub fn new() -> Self {
6436 Self::new_from_buf(Vec::new())
6437 }
6438 pub fn new_from_buf(buf: Vec<u8>) -> Self {
6439 Self {
6440 flags: 0,
6441 buf: RequestBuf::Own(buf),
6442 writeback: None,
6443 }
6444 }
6445 pub fn into_buf(self) -> Vec<u8> {
6446 match self.buf {
6447 RequestBuf::Own(buf) => buf,
6448 _ => unreachable!(),
6449 }
6450 }
6451}
6452impl<'buf> Request<'buf> {
6453 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
6454 buf.clear();
6455 Self::new_extend(buf)
6456 }
6457 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
6458 Self {
6459 flags: 0,
6460 buf: RequestBuf::Ref(buf),
6461 writeback: None,
6462 }
6463 }
6464 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
6465 let Some(writeback) = &mut self.writeback else {
6466 return;
6467 };
6468 **writeback = Some(RequestInfo {
6469 protocol,
6470 flags: self.flags,
6471 name,
6472 lookup,
6473 })
6474 }
6475 pub fn buf(&self) -> &Vec<u8> {
6476 self.buf.buf()
6477 }
6478 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
6479 self.buf.buf_mut()
6480 }
6481 #[doc = "Set `NLM_F_CREATE` flag"]
6482 pub fn set_create(mut self) -> Self {
6483 self.flags |= consts::NLM_F_CREATE as u16;
6484 self
6485 }
6486 #[doc = "Set `NLM_F_EXCL` flag"]
6487 pub fn set_excl(mut self) -> Self {
6488 self.flags |= consts::NLM_F_EXCL as u16;
6489 self
6490 }
6491 #[doc = "Set `NLM_F_REPLACE` flag"]
6492 pub fn set_replace(mut self) -> Self {
6493 self.flags |= consts::NLM_F_REPLACE as u16;
6494 self
6495 }
6496 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
6497 pub fn set_change(self) -> Self {
6498 self.set_create().set_replace()
6499 }
6500 #[doc = "Set `NLM_F_APPEND` flag"]
6501 pub fn set_append(mut self) -> Self {
6502 self.flags |= consts::NLM_F_APPEND as u16;
6503 self
6504 }
6505 #[doc = "Set `self.flags |= flags`"]
6506 pub fn set_flags(mut self, flags: u16) -> Self {
6507 self.flags |= flags;
6508 self
6509 }
6510 #[doc = "Set `self.flags ^= self.flags & flags`"]
6511 pub fn unset_flags(mut self, flags: u16) -> Self {
6512 self.flags ^= self.flags & flags;
6513 self
6514 }
6515 #[doc = "Set `NLM_F_DUMP` flag"]
6516 fn set_dump(mut self) -> Self {
6517 self.flags |= consts::NLM_F_DUMP as u16;
6518 self
6519 }
6520 #[doc = "get / dump entries\n\nRequest attributes:\n- [.push_status()](PushConntrackAttrs::push_status)\n- [.push_mark()](PushConntrackAttrs::push_mark)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n- [.nested_filter()](PushConntrackAttrs::nested_filter)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n\n"]
6521 pub fn op_get_dump(self, header: &Nfgenmsg) -> OpGetDump<'buf> {
6522 let mut res = OpGetDump::new(self, header);
6523 res.request
6524 .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
6525 res
6526 }
6527 #[doc = "get / dump entries\n\nRequest attributes:\n- [.nested_tuple_orig()](PushConntrackAttrs::nested_tuple_orig)\n- [.nested_tuple_reply()](PushConntrackAttrs::nested_tuple_reply)\n- [.push_zone()](PushConntrackAttrs::push_zone)\n\nReply attributes:\n- [.get_tuple_orig()](IterableConntrackAttrs::get_tuple_orig)\n- [.get_tuple_reply()](IterableConntrackAttrs::get_tuple_reply)\n- [.get_status()](IterableConntrackAttrs::get_status)\n- [.get_protoinfo()](IterableConntrackAttrs::get_protoinfo)\n- [.get_help()](IterableConntrackAttrs::get_help)\n- [.get_nat_src()](IterableConntrackAttrs::get_nat_src)\n- [.get_timeout()](IterableConntrackAttrs::get_timeout)\n- [.get_mark()](IterableConntrackAttrs::get_mark)\n- [.get_counters_orig()](IterableConntrackAttrs::get_counters_orig)\n- [.get_counters_reply()](IterableConntrackAttrs::get_counters_reply)\n- [.get_use()](IterableConntrackAttrs::get_use)\n- [.get_id()](IterableConntrackAttrs::get_id)\n- [.get_nat_dst()](IterableConntrackAttrs::get_nat_dst)\n- [.get_tuple_master()](IterableConntrackAttrs::get_tuple_master)\n- [.get_seq_adj_orig()](IterableConntrackAttrs::get_seq_adj_orig)\n- [.get_seq_adj_reply()](IterableConntrackAttrs::get_seq_adj_reply)\n- [.get_zone()](IterableConntrackAttrs::get_zone)\n- [.get_secctx()](IterableConntrackAttrs::get_secctx)\n- [.get_labels()](IterableConntrackAttrs::get_labels)\n- [.get_synproxy()](IterableConntrackAttrs::get_synproxy)\n\n"]
6528 pub fn op_get_do(self, header: &Nfgenmsg) -> OpGetDo<'buf> {
6529 let mut res = OpGetDo::new(self, header);
6530 res.request
6531 .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
6532 res
6533 }
6534 #[doc = "dump pcpu conntrack stats\n\nReply attributes:\n- [.get_searched()](IterableConntrackStatsAttrs::get_searched)\n- [.get_found()](IterableConntrackStatsAttrs::get_found)\n- [.get_insert()](IterableConntrackStatsAttrs::get_insert)\n- [.get_insert_failed()](IterableConntrackStatsAttrs::get_insert_failed)\n- [.get_drop()](IterableConntrackStatsAttrs::get_drop)\n- [.get_early_drop()](IterableConntrackStatsAttrs::get_early_drop)\n- [.get_error()](IterableConntrackStatsAttrs::get_error)\n- [.get_search_restart()](IterableConntrackStatsAttrs::get_search_restart)\n- [.get_clash_resolve()](IterableConntrackStatsAttrs::get_clash_resolve)\n- [.get_chain_toolong()](IterableConntrackStatsAttrs::get_chain_toolong)\n\n"]
6535 pub fn op_get_stats_dump(self, header: &Nfgenmsg) -> OpGetStatsDump<'buf> {
6536 let mut res = OpGetStatsDump::new(self, header);
6537 res.request
6538 .do_writeback(res.protocol(), "op-get-stats-dump", OpGetStatsDump::lookup);
6539 res
6540 }
6541}
6542#[cfg(test)]
6543mod generated_tests {
6544 use super::*;
6545 #[test]
6546 fn tests() {
6547 let _ = IterableConntrackAttrs::get_counters_orig;
6548 let _ = IterableConntrackAttrs::get_counters_reply;
6549 let _ = IterableConntrackAttrs::get_help;
6550 let _ = IterableConntrackAttrs::get_id;
6551 let _ = IterableConntrackAttrs::get_labels;
6552 let _ = IterableConntrackAttrs::get_mark;
6553 let _ = IterableConntrackAttrs::get_nat_dst;
6554 let _ = IterableConntrackAttrs::get_nat_src;
6555 let _ = IterableConntrackAttrs::get_protoinfo;
6556 let _ = IterableConntrackAttrs::get_secctx;
6557 let _ = IterableConntrackAttrs::get_seq_adj_orig;
6558 let _ = IterableConntrackAttrs::get_seq_adj_reply;
6559 let _ = IterableConntrackAttrs::get_status;
6560 let _ = IterableConntrackAttrs::get_synproxy;
6561 let _ = IterableConntrackAttrs::get_timeout;
6562 let _ = IterableConntrackAttrs::get_tuple_master;
6563 let _ = IterableConntrackAttrs::get_tuple_orig;
6564 let _ = IterableConntrackAttrs::get_tuple_reply;
6565 let _ = IterableConntrackAttrs::get_use;
6566 let _ = IterableConntrackAttrs::get_zone;
6567 let _ = IterableConntrackStatsAttrs::get_chain_toolong;
6568 let _ = IterableConntrackStatsAttrs::get_clash_resolve;
6569 let _ = IterableConntrackStatsAttrs::get_drop;
6570 let _ = IterableConntrackStatsAttrs::get_early_drop;
6571 let _ = IterableConntrackStatsAttrs::get_error;
6572 let _ = IterableConntrackStatsAttrs::get_found;
6573 let _ = IterableConntrackStatsAttrs::get_insert;
6574 let _ = IterableConntrackStatsAttrs::get_insert_failed;
6575 let _ = IterableConntrackStatsAttrs::get_search_restart;
6576 let _ = IterableConntrackStatsAttrs::get_searched;
6577 let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_filter;
6578 let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_tuple_orig;
6579 let _ = PushConntrackAttrs::<&mut Vec<u8>>::nested_tuple_reply;
6580 let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_mark;
6581 let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_status;
6582 let _ = PushConntrackAttrs::<&mut Vec<u8>>::push_zone;
6583 }
6584}