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