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::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &CStr = c"conntrack";
17pub const PROTONUM: u16 = 12u16;
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum NfCtTcpFlags {
21 WindowScale = 1 << 0,
22 SackPerm = 1 << 1,
23 CloseInit = 1 << 2,
24 BeLiberal = 1 << 3,
25 Unacked = 1 << 4,
26 Maxack = 1 << 5,
27 ChallengeAck = 1 << 6,
28 SimultaneousOpen = 1 << 7,
29}
30impl NfCtTcpFlags {
31 pub fn from_value(value: u64) -> Option<Self> {
32 Some(match value {
33 n if n == 1 << 0 => Self::WindowScale,
34 n if n == 1 << 1 => Self::SackPerm,
35 n if n == 1 << 2 => Self::CloseInit,
36 n if n == 1 << 3 => Self::BeLiberal,
37 n if n == 1 << 4 => Self::Unacked,
38 n if n == 1 << 5 => Self::Maxack,
39 n if n == 1 << 6 => Self::ChallengeAck,
40 n if n == 1 << 7 => Self::SimultaneousOpen,
41 _ => return None,
42 })
43 }
44}
45#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
46#[derive(Debug, Clone, Copy)]
47pub enum NfCtTcpState {
48 None = 0,
49 SynSent = 1,
50 SynRecv = 2,
51 Established = 3,
52 FinWait = 4,
53 CloseWait = 5,
54 LastAck = 6,
55 TimeWait = 7,
56 Close = 8,
57 SynSent2 = 9,
58 Max = 10,
59 Ignore = 11,
60 Retrans = 12,
61 Unack = 13,
62 TimeoutMax = 14,
63}
64impl NfCtTcpState {
65 pub fn from_value(value: u64) -> Option<Self> {
66 Some(match value {
67 0 => Self::None,
68 1 => Self::SynSent,
69 2 => Self::SynRecv,
70 3 => Self::Established,
71 4 => Self::FinWait,
72 5 => Self::CloseWait,
73 6 => Self::LastAck,
74 7 => Self::TimeWait,
75 8 => Self::Close,
76 9 => Self::SynSent2,
77 10 => Self::Max,
78 11 => Self::Ignore,
79 12 => Self::Retrans,
80 13 => Self::Unack,
81 14 => Self::TimeoutMax,
82 _ => return None,
83 })
84 }
85}
86#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
87#[derive(Debug, Clone, Copy)]
88pub enum NfCtSctpState {
89 None = 0,
90 Cloned = 1,
91 CookieWait = 2,
92 CookieEchoed = 3,
93 Established = 4,
94 ShutdownSent = 5,
95 ShutdownReceived = 6,
96 ShutdownAckSent = 7,
97 ShutdownHeartbeatSent = 8,
98}
99impl NfCtSctpState {
100 pub fn from_value(value: u64) -> Option<Self> {
101 Some(match value {
102 0 => Self::None,
103 1 => Self::Cloned,
104 2 => Self::CookieWait,
105 3 => Self::CookieEchoed,
106 4 => Self::Established,
107 5 => Self::ShutdownSent,
108 6 => Self::ShutdownReceived,
109 7 => Self::ShutdownAckSent,
110 8 => Self::ShutdownHeartbeatSent,
111 _ => return None,
112 })
113 }
114}
115#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
116#[derive(Debug, Clone, Copy)]
117pub enum NfCtStatus {
118 Expected = 1 << 0,
119 SeenReply = 1 << 1,
120 Assured = 1 << 2,
121 Confirmed = 1 << 3,
122 SrcNat = 1 << 4,
123 DstNat = 1 << 5,
124 SeqAdj = 1 << 6,
125 SrcNatDone = 1 << 7,
126 DstNatDone = 1 << 8,
127 Dying = 1 << 9,
128 FixedTimeout = 1 << 10,
129 Template = 1 << 11,
130 NatClash = 1 << 12,
131 Helper = 1 << 13,
132 Offload = 1 << 14,
133 HwOffload = 1 << 15,
134}
135impl NfCtStatus {
136 pub fn from_value(value: u64) -> Option<Self> {
137 Some(match value {
138 n if n == 1 << 0 => Self::Expected,
139 n if n == 1 << 1 => Self::SeenReply,
140 n if n == 1 << 2 => Self::Assured,
141 n if n == 1 << 3 => Self::Confirmed,
142 n if n == 1 << 4 => Self::SrcNat,
143 n if n == 1 << 5 => Self::DstNat,
144 n if n == 1 << 6 => Self::SeqAdj,
145 n if n == 1 << 7 => Self::SrcNatDone,
146 n if n == 1 << 8 => Self::DstNatDone,
147 n if n == 1 << 9 => Self::Dying,
148 n if n == 1 << 10 => Self::FixedTimeout,
149 n if n == 1 << 11 => Self::Template,
150 n if n == 1 << 12 => Self::NatClash,
151 n if n == 1 << 13 => Self::Helper,
152 n if n == 1 << 14 => Self::Offload,
153 n if n == 1 << 15 => Self::HwOffload,
154 _ => return None,
155 })
156 }
157}
158#[derive(Clone)]
159pub enum CounterAttrs<'a> {
160 Packets(u64),
161 Bytes(u64),
162 PacketsOld(u32),
163 BytesOld(u32),
164 Pad(&'a [u8]),
165}
166impl<'a> IterableCounterAttrs<'a> {
167 pub fn get_packets(&self) -> Result<u64, ErrorContext> {
168 let mut iter = self.clone();
169 iter.pos = 0;
170 for attr in iter {
171 if let CounterAttrs::Packets(val) = attr? {
172 return Ok(val);
173 }
174 }
175 Err(ErrorContext::new_missing(
176 "CounterAttrs",
177 "Packets",
178 self.orig_loc,
179 self.buf.as_ptr() as usize,
180 ))
181 }
182 pub fn get_bytes(&self) -> Result<u64, ErrorContext> {
183 let mut iter = self.clone();
184 iter.pos = 0;
185 for attr in iter {
186 if let CounterAttrs::Bytes(val) = attr? {
187 return Ok(val);
188 }
189 }
190 Err(ErrorContext::new_missing(
191 "CounterAttrs",
192 "Bytes",
193 self.orig_loc,
194 self.buf.as_ptr() as usize,
195 ))
196 }
197 pub fn get_packets_old(&self) -> Result<u32, ErrorContext> {
198 let mut iter = self.clone();
199 iter.pos = 0;
200 for attr in iter {
201 if let CounterAttrs::PacketsOld(val) = attr? {
202 return Ok(val);
203 }
204 }
205 Err(ErrorContext::new_missing(
206 "CounterAttrs",
207 "PacketsOld",
208 self.orig_loc,
209 self.buf.as_ptr() as usize,
210 ))
211 }
212 pub fn get_bytes_old(&self) -> Result<u32, ErrorContext> {
213 let mut iter = self.clone();
214 iter.pos = 0;
215 for attr in iter {
216 if let CounterAttrs::BytesOld(val) = attr? {
217 return Ok(val);
218 }
219 }
220 Err(ErrorContext::new_missing(
221 "CounterAttrs",
222 "BytesOld",
223 self.orig_loc,
224 self.buf.as_ptr() as usize,
225 ))
226 }
227 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
228 let mut iter = self.clone();
229 iter.pos = 0;
230 for attr in iter {
231 if let CounterAttrs::Pad(val) = attr? {
232 return Ok(val);
233 }
234 }
235 Err(ErrorContext::new_missing(
236 "CounterAttrs",
237 "Pad",
238 self.orig_loc,
239 self.buf.as_ptr() as usize,
240 ))
241 }
242}
243impl CounterAttrs<'_> {
244 pub fn new<'a>(buf: &'a [u8]) -> IterableCounterAttrs<'a> {
245 IterableCounterAttrs::with_loc(buf, buf.as_ptr() as usize)
246 }
247 fn attr_from_type(r#type: u16) -> Option<&'static str> {
248 let res = match r#type {
249 1u16 => "Packets",
250 2u16 => "Bytes",
251 3u16 => "PacketsOld",
252 4u16 => "BytesOld",
253 5u16 => "Pad",
254 _ => return None,
255 };
256 Some(res)
257 }
258}
259#[derive(Clone, Copy, Default)]
260pub struct IterableCounterAttrs<'a> {
261 buf: &'a [u8],
262 pos: usize,
263 orig_loc: usize,
264}
265impl<'a> IterableCounterAttrs<'a> {
266 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
267 Self {
268 buf,
269 pos: 0,
270 orig_loc,
271 }
272 }
273 pub fn get_buf(&self) -> &'a [u8] {
274 self.buf
275 }
276}
277impl<'a> Iterator for IterableCounterAttrs<'a> {
278 type Item = Result<CounterAttrs<'a>, ErrorContext>;
279 fn next(&mut self) -> Option<Self::Item> {
280 let pos = self.pos;
281 let mut r#type;
282 loop {
283 r#type = None;
284 if self.buf.len() == self.pos {
285 return None;
286 }
287 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
288 break;
289 };
290 r#type = Some(header.r#type);
291 let res = match header.r#type {
292 1u16 => CounterAttrs::Packets({
293 let res = parse_be_u64(next);
294 let Some(val) = res else { break };
295 val
296 }),
297 2u16 => CounterAttrs::Bytes({
298 let res = parse_be_u64(next);
299 let Some(val) = res else { break };
300 val
301 }),
302 3u16 => CounterAttrs::PacketsOld({
303 let res = parse_u32(next);
304 let Some(val) = res else { break };
305 val
306 }),
307 4u16 => CounterAttrs::BytesOld({
308 let res = parse_u32(next);
309 let Some(val) = res else { break };
310 val
311 }),
312 5u16 => CounterAttrs::Pad({
313 let res = Some(next);
314 let Some(val) = res else { break };
315 val
316 }),
317 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
318 n => continue,
319 };
320 return Some(Ok(res));
321 }
322 Some(Err(ErrorContext::new(
323 "CounterAttrs",
324 r#type.and_then(|t| CounterAttrs::attr_from_type(t)),
325 self.orig_loc,
326 self.buf.as_ptr().wrapping_add(pos) as usize,
327 )))
328 }
329}
330impl<'a> std::fmt::Debug for IterableCounterAttrs<'_> {
331 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332 let mut fmt = f.debug_struct("CounterAttrs");
333 for attr in self.clone() {
334 let attr = match attr {
335 Ok(a) => a,
336 Err(err) => {
337 fmt.finish()?;
338 f.write_str("Err(")?;
339 err.fmt(f)?;
340 return f.write_str(")");
341 }
342 };
343 match attr {
344 CounterAttrs::Packets(val) => fmt.field("Packets", &val),
345 CounterAttrs::Bytes(val) => fmt.field("Bytes", &val),
346 CounterAttrs::PacketsOld(val) => fmt.field("PacketsOld", &val),
347 CounterAttrs::BytesOld(val) => fmt.field("BytesOld", &val),
348 CounterAttrs::Pad(val) => fmt.field("Pad", &val),
349 };
350 }
351 fmt.finish()
352 }
353}
354impl IterableCounterAttrs<'_> {
355 pub fn lookup_attr(
356 &self,
357 offset: usize,
358 missing_type: Option<u16>,
359 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
360 let mut stack = Vec::new();
361 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
362 if cur == offset {
363 stack.push(("CounterAttrs", offset));
364 return (
365 stack,
366 missing_type.and_then(|t| CounterAttrs::attr_from_type(t)),
367 );
368 }
369 if cur > offset || cur + self.buf.len() < offset {
370 return (stack, None);
371 }
372 let mut attrs = self.clone();
373 let mut last_off = cur + attrs.pos;
374 while let Some(attr) = attrs.next() {
375 let Ok(attr) = attr else { break };
376 match attr {
377 CounterAttrs::Packets(val) => {
378 if last_off == offset {
379 stack.push(("Packets", last_off));
380 break;
381 }
382 }
383 CounterAttrs::Bytes(val) => {
384 if last_off == offset {
385 stack.push(("Bytes", last_off));
386 break;
387 }
388 }
389 CounterAttrs::PacketsOld(val) => {
390 if last_off == offset {
391 stack.push(("PacketsOld", last_off));
392 break;
393 }
394 }
395 CounterAttrs::BytesOld(val) => {
396 if last_off == offset {
397 stack.push(("BytesOld", last_off));
398 break;
399 }
400 }
401 CounterAttrs::Pad(val) => {
402 if last_off == offset {
403 stack.push(("Pad", last_off));
404 break;
405 }
406 }
407 _ => {}
408 };
409 last_off = cur + attrs.pos;
410 }
411 if !stack.is_empty() {
412 stack.push(("CounterAttrs", cur));
413 }
414 (stack, None)
415 }
416}
417#[derive(Clone)]
418pub enum TupleProtoAttrs {
419 #[doc = "l4 protocol number"]
420 ProtoNum(u8),
421 #[doc = "l4 source port"]
422 ProtoSrcPort(u16),
423 #[doc = "l4 source port"]
424 ProtoDstPort(u16),
425 #[doc = "l4 icmp id"]
426 ProtoIcmpId(u16),
427 ProtoIcmpType(u8),
428 ProtoIcmpCode(u8),
429 #[doc = "l4 icmp id"]
430 ProtoIcmpv6Id(u16),
431 ProtoIcmpv6Type(u8),
432 ProtoIcmpv6Code(u8),
433}
434impl<'a> IterableTupleProtoAttrs<'a> {
435 #[doc = "l4 protocol number"]
436 pub fn get_proto_num(&self) -> Result<u8, ErrorContext> {
437 let mut iter = self.clone();
438 iter.pos = 0;
439 for attr in iter {
440 if let TupleProtoAttrs::ProtoNum(val) = attr? {
441 return Ok(val);
442 }
443 }
444 Err(ErrorContext::new_missing(
445 "TupleProtoAttrs",
446 "ProtoNum",
447 self.orig_loc,
448 self.buf.as_ptr() as usize,
449 ))
450 }
451 #[doc = "l4 source port"]
452 pub fn get_proto_src_port(&self) -> Result<u16, ErrorContext> {
453 let mut iter = self.clone();
454 iter.pos = 0;
455 for attr in iter {
456 if let TupleProtoAttrs::ProtoSrcPort(val) = attr? {
457 return Ok(val);
458 }
459 }
460 Err(ErrorContext::new_missing(
461 "TupleProtoAttrs",
462 "ProtoSrcPort",
463 self.orig_loc,
464 self.buf.as_ptr() as usize,
465 ))
466 }
467 #[doc = "l4 source port"]
468 pub fn get_proto_dst_port(&self) -> Result<u16, ErrorContext> {
469 let mut iter = self.clone();
470 iter.pos = 0;
471 for attr in iter {
472 if let TupleProtoAttrs::ProtoDstPort(val) = attr? {
473 return Ok(val);
474 }
475 }
476 Err(ErrorContext::new_missing(
477 "TupleProtoAttrs",
478 "ProtoDstPort",
479 self.orig_loc,
480 self.buf.as_ptr() as usize,
481 ))
482 }
483 #[doc = "l4 icmp id"]
484 pub fn get_proto_icmp_id(&self) -> Result<u16, ErrorContext> {
485 let mut iter = self.clone();
486 iter.pos = 0;
487 for attr in iter {
488 if let TupleProtoAttrs::ProtoIcmpId(val) = attr? {
489 return Ok(val);
490 }
491 }
492 Err(ErrorContext::new_missing(
493 "TupleProtoAttrs",
494 "ProtoIcmpId",
495 self.orig_loc,
496 self.buf.as_ptr() as usize,
497 ))
498 }
499 pub fn get_proto_icmp_type(&self) -> Result<u8, ErrorContext> {
500 let mut iter = self.clone();
501 iter.pos = 0;
502 for attr in iter {
503 if let TupleProtoAttrs::ProtoIcmpType(val) = attr? {
504 return Ok(val);
505 }
506 }
507 Err(ErrorContext::new_missing(
508 "TupleProtoAttrs",
509 "ProtoIcmpType",
510 self.orig_loc,
511 self.buf.as_ptr() as usize,
512 ))
513 }
514 pub fn get_proto_icmp_code(&self) -> Result<u8, ErrorContext> {
515 let mut iter = self.clone();
516 iter.pos = 0;
517 for attr in iter {
518 if let TupleProtoAttrs::ProtoIcmpCode(val) = attr? {
519 return Ok(val);
520 }
521 }
522 Err(ErrorContext::new_missing(
523 "TupleProtoAttrs",
524 "ProtoIcmpCode",
525 self.orig_loc,
526 self.buf.as_ptr() as usize,
527 ))
528 }
529 #[doc = "l4 icmp id"]
530 pub fn get_proto_icmpv6_id(&self) -> Result<u16, ErrorContext> {
531 let mut iter = self.clone();
532 iter.pos = 0;
533 for attr in iter {
534 if let TupleProtoAttrs::ProtoIcmpv6Id(val) = attr? {
535 return Ok(val);
536 }
537 }
538 Err(ErrorContext::new_missing(
539 "TupleProtoAttrs",
540 "ProtoIcmpv6Id",
541 self.orig_loc,
542 self.buf.as_ptr() as usize,
543 ))
544 }
545 pub fn get_proto_icmpv6_type(&self) -> Result<u8, ErrorContext> {
546 let mut iter = self.clone();
547 iter.pos = 0;
548 for attr in iter {
549 if let TupleProtoAttrs::ProtoIcmpv6Type(val) = attr? {
550 return Ok(val);
551 }
552 }
553 Err(ErrorContext::new_missing(
554 "TupleProtoAttrs",
555 "ProtoIcmpv6Type",
556 self.orig_loc,
557 self.buf.as_ptr() as usize,
558 ))
559 }
560 pub fn get_proto_icmpv6_code(&self) -> Result<u8, ErrorContext> {
561 let mut iter = self.clone();
562 iter.pos = 0;
563 for attr in iter {
564 if let TupleProtoAttrs::ProtoIcmpv6Code(val) = attr? {
565 return Ok(val);
566 }
567 }
568 Err(ErrorContext::new_missing(
569 "TupleProtoAttrs",
570 "ProtoIcmpv6Code",
571 self.orig_loc,
572 self.buf.as_ptr() as usize,
573 ))
574 }
575}
576impl TupleProtoAttrs {
577 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleProtoAttrs<'a> {
578 IterableTupleProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
579 }
580 fn attr_from_type(r#type: u16) -> Option<&'static str> {
581 let res = match r#type {
582 1u16 => "ProtoNum",
583 2u16 => "ProtoSrcPort",
584 3u16 => "ProtoDstPort",
585 4u16 => "ProtoIcmpId",
586 5u16 => "ProtoIcmpType",
587 6u16 => "ProtoIcmpCode",
588 7u16 => "ProtoIcmpv6Id",
589 8u16 => "ProtoIcmpv6Type",
590 9u16 => "ProtoIcmpv6Code",
591 _ => return None,
592 };
593 Some(res)
594 }
595}
596#[derive(Clone, Copy, Default)]
597pub struct IterableTupleProtoAttrs<'a> {
598 buf: &'a [u8],
599 pos: usize,
600 orig_loc: usize,
601}
602impl<'a> IterableTupleProtoAttrs<'a> {
603 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
604 Self {
605 buf,
606 pos: 0,
607 orig_loc,
608 }
609 }
610 pub fn get_buf(&self) -> &'a [u8] {
611 self.buf
612 }
613}
614impl<'a> Iterator for IterableTupleProtoAttrs<'a> {
615 type Item = Result<TupleProtoAttrs, ErrorContext>;
616 fn next(&mut self) -> Option<Self::Item> {
617 let pos = self.pos;
618 let mut r#type;
619 loop {
620 r#type = None;
621 if self.buf.len() == self.pos {
622 return None;
623 }
624 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
625 break;
626 };
627 r#type = Some(header.r#type);
628 let res = match header.r#type {
629 1u16 => TupleProtoAttrs::ProtoNum({
630 let res = parse_u8(next);
631 let Some(val) = res else { break };
632 val
633 }),
634 2u16 => TupleProtoAttrs::ProtoSrcPort({
635 let res = parse_be_u16(next);
636 let Some(val) = res else { break };
637 val
638 }),
639 3u16 => TupleProtoAttrs::ProtoDstPort({
640 let res = parse_be_u16(next);
641 let Some(val) = res else { break };
642 val
643 }),
644 4u16 => TupleProtoAttrs::ProtoIcmpId({
645 let res = parse_be_u16(next);
646 let Some(val) = res else { break };
647 val
648 }),
649 5u16 => TupleProtoAttrs::ProtoIcmpType({
650 let res = parse_u8(next);
651 let Some(val) = res else { break };
652 val
653 }),
654 6u16 => TupleProtoAttrs::ProtoIcmpCode({
655 let res = parse_u8(next);
656 let Some(val) = res else { break };
657 val
658 }),
659 7u16 => TupleProtoAttrs::ProtoIcmpv6Id({
660 let res = parse_be_u16(next);
661 let Some(val) = res else { break };
662 val
663 }),
664 8u16 => TupleProtoAttrs::ProtoIcmpv6Type({
665 let res = parse_u8(next);
666 let Some(val) = res else { break };
667 val
668 }),
669 9u16 => TupleProtoAttrs::ProtoIcmpv6Code({
670 let res = parse_u8(next);
671 let Some(val) = res else { break };
672 val
673 }),
674 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
675 n => continue,
676 };
677 return Some(Ok(res));
678 }
679 Some(Err(ErrorContext::new(
680 "TupleProtoAttrs",
681 r#type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
682 self.orig_loc,
683 self.buf.as_ptr().wrapping_add(pos) as usize,
684 )))
685 }
686}
687impl std::fmt::Debug for IterableTupleProtoAttrs<'_> {
688 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
689 let mut fmt = f.debug_struct("TupleProtoAttrs");
690 for attr in self.clone() {
691 let attr = match attr {
692 Ok(a) => a,
693 Err(err) => {
694 fmt.finish()?;
695 f.write_str("Err(")?;
696 err.fmt(f)?;
697 return f.write_str(")");
698 }
699 };
700 match attr {
701 TupleProtoAttrs::ProtoNum(val) => fmt.field("ProtoNum", &val),
702 TupleProtoAttrs::ProtoSrcPort(val) => fmt.field("ProtoSrcPort", &val),
703 TupleProtoAttrs::ProtoDstPort(val) => fmt.field("ProtoDstPort", &val),
704 TupleProtoAttrs::ProtoIcmpId(val) => fmt.field("ProtoIcmpId", &val),
705 TupleProtoAttrs::ProtoIcmpType(val) => fmt.field("ProtoIcmpType", &val),
706 TupleProtoAttrs::ProtoIcmpCode(val) => fmt.field("ProtoIcmpCode", &val),
707 TupleProtoAttrs::ProtoIcmpv6Id(val) => fmt.field("ProtoIcmpv6Id", &val),
708 TupleProtoAttrs::ProtoIcmpv6Type(val) => fmt.field("ProtoIcmpv6Type", &val),
709 TupleProtoAttrs::ProtoIcmpv6Code(val) => fmt.field("ProtoIcmpv6Code", &val),
710 };
711 }
712 fmt.finish()
713 }
714}
715impl IterableTupleProtoAttrs<'_> {
716 pub fn lookup_attr(
717 &self,
718 offset: usize,
719 missing_type: Option<u16>,
720 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
721 let mut stack = Vec::new();
722 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
723 if cur == offset {
724 stack.push(("TupleProtoAttrs", offset));
725 return (
726 stack,
727 missing_type.and_then(|t| TupleProtoAttrs::attr_from_type(t)),
728 );
729 }
730 if cur > offset || cur + self.buf.len() < offset {
731 return (stack, None);
732 }
733 let mut attrs = self.clone();
734 let mut last_off = cur + attrs.pos;
735 while let Some(attr) = attrs.next() {
736 let Ok(attr) = attr else { break };
737 match attr {
738 TupleProtoAttrs::ProtoNum(val) => {
739 if last_off == offset {
740 stack.push(("ProtoNum", last_off));
741 break;
742 }
743 }
744 TupleProtoAttrs::ProtoSrcPort(val) => {
745 if last_off == offset {
746 stack.push(("ProtoSrcPort", last_off));
747 break;
748 }
749 }
750 TupleProtoAttrs::ProtoDstPort(val) => {
751 if last_off == offset {
752 stack.push(("ProtoDstPort", last_off));
753 break;
754 }
755 }
756 TupleProtoAttrs::ProtoIcmpId(val) => {
757 if last_off == offset {
758 stack.push(("ProtoIcmpId", last_off));
759 break;
760 }
761 }
762 TupleProtoAttrs::ProtoIcmpType(val) => {
763 if last_off == offset {
764 stack.push(("ProtoIcmpType", last_off));
765 break;
766 }
767 }
768 TupleProtoAttrs::ProtoIcmpCode(val) => {
769 if last_off == offset {
770 stack.push(("ProtoIcmpCode", last_off));
771 break;
772 }
773 }
774 TupleProtoAttrs::ProtoIcmpv6Id(val) => {
775 if last_off == offset {
776 stack.push(("ProtoIcmpv6Id", last_off));
777 break;
778 }
779 }
780 TupleProtoAttrs::ProtoIcmpv6Type(val) => {
781 if last_off == offset {
782 stack.push(("ProtoIcmpv6Type", last_off));
783 break;
784 }
785 }
786 TupleProtoAttrs::ProtoIcmpv6Code(val) => {
787 if last_off == offset {
788 stack.push(("ProtoIcmpv6Code", last_off));
789 break;
790 }
791 }
792 _ => {}
793 };
794 last_off = cur + attrs.pos;
795 }
796 if !stack.is_empty() {
797 stack.push(("TupleProtoAttrs", cur));
798 }
799 (stack, None)
800 }
801}
802#[derive(Clone)]
803pub enum TupleIpAttrs {
804 #[doc = "ipv4 source address"]
805 IpV4Src(std::net::Ipv4Addr),
806 #[doc = "ipv4 destination address"]
807 IpV4Dst(std::net::Ipv4Addr),
808 #[doc = "ipv6 source address"]
809 IpV6Src(std::net::Ipv6Addr),
810 #[doc = "ipv6 destination address"]
811 IpV6Dst(std::net::Ipv6Addr),
812}
813impl<'a> IterableTupleIpAttrs<'a> {
814 #[doc = "ipv4 source address"]
815 pub fn get_ip_v4_src(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
816 let mut iter = self.clone();
817 iter.pos = 0;
818 for attr in iter {
819 if let TupleIpAttrs::IpV4Src(val) = attr? {
820 return Ok(val);
821 }
822 }
823 Err(ErrorContext::new_missing(
824 "TupleIpAttrs",
825 "IpV4Src",
826 self.orig_loc,
827 self.buf.as_ptr() as usize,
828 ))
829 }
830 #[doc = "ipv4 destination address"]
831 pub fn get_ip_v4_dst(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
832 let mut iter = self.clone();
833 iter.pos = 0;
834 for attr in iter {
835 if let TupleIpAttrs::IpV4Dst(val) = attr? {
836 return Ok(val);
837 }
838 }
839 Err(ErrorContext::new_missing(
840 "TupleIpAttrs",
841 "IpV4Dst",
842 self.orig_loc,
843 self.buf.as_ptr() as usize,
844 ))
845 }
846 #[doc = "ipv6 source address"]
847 pub fn get_ip_v6_src(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
848 let mut iter = self.clone();
849 iter.pos = 0;
850 for attr in iter {
851 if let TupleIpAttrs::IpV6Src(val) = attr? {
852 return Ok(val);
853 }
854 }
855 Err(ErrorContext::new_missing(
856 "TupleIpAttrs",
857 "IpV6Src",
858 self.orig_loc,
859 self.buf.as_ptr() as usize,
860 ))
861 }
862 #[doc = "ipv6 destination address"]
863 pub fn get_ip_v6_dst(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
864 let mut iter = self.clone();
865 iter.pos = 0;
866 for attr in iter {
867 if let TupleIpAttrs::IpV6Dst(val) = attr? {
868 return Ok(val);
869 }
870 }
871 Err(ErrorContext::new_missing(
872 "TupleIpAttrs",
873 "IpV6Dst",
874 self.orig_loc,
875 self.buf.as_ptr() as usize,
876 ))
877 }
878}
879impl TupleIpAttrs {
880 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleIpAttrs<'a> {
881 IterableTupleIpAttrs::with_loc(buf, buf.as_ptr() as usize)
882 }
883 fn attr_from_type(r#type: u16) -> Option<&'static str> {
884 let res = match r#type {
885 1u16 => "IpV4Src",
886 2u16 => "IpV4Dst",
887 3u16 => "IpV6Src",
888 4u16 => "IpV6Dst",
889 _ => return None,
890 };
891 Some(res)
892 }
893}
894#[derive(Clone, Copy, Default)]
895pub struct IterableTupleIpAttrs<'a> {
896 buf: &'a [u8],
897 pos: usize,
898 orig_loc: usize,
899}
900impl<'a> IterableTupleIpAttrs<'a> {
901 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
902 Self {
903 buf,
904 pos: 0,
905 orig_loc,
906 }
907 }
908 pub fn get_buf(&self) -> &'a [u8] {
909 self.buf
910 }
911}
912impl<'a> Iterator for IterableTupleIpAttrs<'a> {
913 type Item = Result<TupleIpAttrs, ErrorContext>;
914 fn next(&mut self) -> Option<Self::Item> {
915 let pos = self.pos;
916 let mut r#type;
917 loop {
918 r#type = None;
919 if self.buf.len() == self.pos {
920 return None;
921 }
922 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
923 break;
924 };
925 r#type = Some(header.r#type);
926 let res = match header.r#type {
927 1u16 => TupleIpAttrs::IpV4Src({
928 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
929 let Some(val) = res else { break };
930 val
931 }),
932 2u16 => TupleIpAttrs::IpV4Dst({
933 let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
934 let Some(val) = res else { break };
935 val
936 }),
937 3u16 => TupleIpAttrs::IpV6Src({
938 let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
939 let Some(val) = res else { break };
940 val
941 }),
942 4u16 => TupleIpAttrs::IpV6Dst({
943 let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
944 let Some(val) = res else { break };
945 val
946 }),
947 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
948 n => continue,
949 };
950 return Some(Ok(res));
951 }
952 Some(Err(ErrorContext::new(
953 "TupleIpAttrs",
954 r#type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
955 self.orig_loc,
956 self.buf.as_ptr().wrapping_add(pos) as usize,
957 )))
958 }
959}
960impl std::fmt::Debug for IterableTupleIpAttrs<'_> {
961 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
962 let mut fmt = f.debug_struct("TupleIpAttrs");
963 for attr in self.clone() {
964 let attr = match attr {
965 Ok(a) => a,
966 Err(err) => {
967 fmt.finish()?;
968 f.write_str("Err(")?;
969 err.fmt(f)?;
970 return f.write_str(")");
971 }
972 };
973 match attr {
974 TupleIpAttrs::IpV4Src(val) => fmt.field("IpV4Src", &val),
975 TupleIpAttrs::IpV4Dst(val) => fmt.field("IpV4Dst", &val),
976 TupleIpAttrs::IpV6Src(val) => fmt.field("IpV6Src", &val),
977 TupleIpAttrs::IpV6Dst(val) => fmt.field("IpV6Dst", &val),
978 };
979 }
980 fmt.finish()
981 }
982}
983impl IterableTupleIpAttrs<'_> {
984 pub fn lookup_attr(
985 &self,
986 offset: usize,
987 missing_type: Option<u16>,
988 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
989 let mut stack = Vec::new();
990 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
991 if cur == offset {
992 stack.push(("TupleIpAttrs", offset));
993 return (
994 stack,
995 missing_type.and_then(|t| TupleIpAttrs::attr_from_type(t)),
996 );
997 }
998 if cur > offset || cur + self.buf.len() < offset {
999 return (stack, None);
1000 }
1001 let mut attrs = self.clone();
1002 let mut last_off = cur + attrs.pos;
1003 while let Some(attr) = attrs.next() {
1004 let Ok(attr) = attr else { break };
1005 match attr {
1006 TupleIpAttrs::IpV4Src(val) => {
1007 if last_off == offset {
1008 stack.push(("IpV4Src", last_off));
1009 break;
1010 }
1011 }
1012 TupleIpAttrs::IpV4Dst(val) => {
1013 if last_off == offset {
1014 stack.push(("IpV4Dst", last_off));
1015 break;
1016 }
1017 }
1018 TupleIpAttrs::IpV6Src(val) => {
1019 if last_off == offset {
1020 stack.push(("IpV6Src", last_off));
1021 break;
1022 }
1023 }
1024 TupleIpAttrs::IpV6Dst(val) => {
1025 if last_off == offset {
1026 stack.push(("IpV6Dst", last_off));
1027 break;
1028 }
1029 }
1030 _ => {}
1031 };
1032 last_off = cur + attrs.pos;
1033 }
1034 if !stack.is_empty() {
1035 stack.push(("TupleIpAttrs", cur));
1036 }
1037 (stack, None)
1038 }
1039}
1040#[derive(Clone)]
1041pub enum TupleAttrs<'a> {
1042 #[doc = "conntrack l3 information"]
1043 TupleIp(IterableTupleIpAttrs<'a>),
1044 #[doc = "conntrack l4 information"]
1045 TupleProto(IterableTupleProtoAttrs<'a>),
1046 #[doc = "conntrack zone id"]
1047 TupleZone(u16),
1048}
1049impl<'a> IterableTupleAttrs<'a> {
1050 #[doc = "conntrack l3 information"]
1051 pub fn get_tuple_ip(&self) -> Result<IterableTupleIpAttrs<'a>, ErrorContext> {
1052 let mut iter = self.clone();
1053 iter.pos = 0;
1054 for attr in iter {
1055 if let TupleAttrs::TupleIp(val) = attr? {
1056 return Ok(val);
1057 }
1058 }
1059 Err(ErrorContext::new_missing(
1060 "TupleAttrs",
1061 "TupleIp",
1062 self.orig_loc,
1063 self.buf.as_ptr() as usize,
1064 ))
1065 }
1066 #[doc = "conntrack l4 information"]
1067 pub fn get_tuple_proto(&self) -> Result<IterableTupleProtoAttrs<'a>, ErrorContext> {
1068 let mut iter = self.clone();
1069 iter.pos = 0;
1070 for attr in iter {
1071 if let TupleAttrs::TupleProto(val) = attr? {
1072 return Ok(val);
1073 }
1074 }
1075 Err(ErrorContext::new_missing(
1076 "TupleAttrs",
1077 "TupleProto",
1078 self.orig_loc,
1079 self.buf.as_ptr() as usize,
1080 ))
1081 }
1082 #[doc = "conntrack zone id"]
1083 pub fn get_tuple_zone(&self) -> Result<u16, ErrorContext> {
1084 let mut iter = self.clone();
1085 iter.pos = 0;
1086 for attr in iter {
1087 if let TupleAttrs::TupleZone(val) = attr? {
1088 return Ok(val);
1089 }
1090 }
1091 Err(ErrorContext::new_missing(
1092 "TupleAttrs",
1093 "TupleZone",
1094 self.orig_loc,
1095 self.buf.as_ptr() as usize,
1096 ))
1097 }
1098}
1099impl TupleAttrs<'_> {
1100 pub fn new<'a>(buf: &'a [u8]) -> IterableTupleAttrs<'a> {
1101 IterableTupleAttrs::with_loc(buf, buf.as_ptr() as usize)
1102 }
1103 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1104 let res = match r#type {
1105 1u16 => "TupleIp",
1106 2u16 => "TupleProto",
1107 3u16 => "TupleZone",
1108 _ => return None,
1109 };
1110 Some(res)
1111 }
1112}
1113#[derive(Clone, Copy, Default)]
1114pub struct IterableTupleAttrs<'a> {
1115 buf: &'a [u8],
1116 pos: usize,
1117 orig_loc: usize,
1118}
1119impl<'a> IterableTupleAttrs<'a> {
1120 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1121 Self {
1122 buf,
1123 pos: 0,
1124 orig_loc,
1125 }
1126 }
1127 pub fn get_buf(&self) -> &'a [u8] {
1128 self.buf
1129 }
1130}
1131impl<'a> Iterator for IterableTupleAttrs<'a> {
1132 type Item = Result<TupleAttrs<'a>, ErrorContext>;
1133 fn next(&mut self) -> Option<Self::Item> {
1134 let pos = self.pos;
1135 let mut r#type;
1136 loop {
1137 r#type = None;
1138 if self.buf.len() == self.pos {
1139 return None;
1140 }
1141 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1142 break;
1143 };
1144 r#type = Some(header.r#type);
1145 let res = match header.r#type {
1146 1u16 => TupleAttrs::TupleIp({
1147 let res = Some(IterableTupleIpAttrs::with_loc(next, self.orig_loc));
1148 let Some(val) = res else { break };
1149 val
1150 }),
1151 2u16 => TupleAttrs::TupleProto({
1152 let res = Some(IterableTupleProtoAttrs::with_loc(next, self.orig_loc));
1153 let Some(val) = res else { break };
1154 val
1155 }),
1156 3u16 => TupleAttrs::TupleZone({
1157 let res = parse_be_u16(next);
1158 let Some(val) = res else { break };
1159 val
1160 }),
1161 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1162 n => continue,
1163 };
1164 return Some(Ok(res));
1165 }
1166 Some(Err(ErrorContext::new(
1167 "TupleAttrs",
1168 r#type.and_then(|t| TupleAttrs::attr_from_type(t)),
1169 self.orig_loc,
1170 self.buf.as_ptr().wrapping_add(pos) as usize,
1171 )))
1172 }
1173}
1174impl<'a> std::fmt::Debug for IterableTupleAttrs<'_> {
1175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1176 let mut fmt = f.debug_struct("TupleAttrs");
1177 for attr in self.clone() {
1178 let attr = match attr {
1179 Ok(a) => a,
1180 Err(err) => {
1181 fmt.finish()?;
1182 f.write_str("Err(")?;
1183 err.fmt(f)?;
1184 return f.write_str(")");
1185 }
1186 };
1187 match attr {
1188 TupleAttrs::TupleIp(val) => fmt.field("TupleIp", &val),
1189 TupleAttrs::TupleProto(val) => fmt.field("TupleProto", &val),
1190 TupleAttrs::TupleZone(val) => fmt.field("TupleZone", &val),
1191 };
1192 }
1193 fmt.finish()
1194 }
1195}
1196impl IterableTupleAttrs<'_> {
1197 pub fn lookup_attr(
1198 &self,
1199 offset: usize,
1200 missing_type: Option<u16>,
1201 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1202 let mut stack = Vec::new();
1203 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1204 if cur == offset {
1205 stack.push(("TupleAttrs", offset));
1206 return (
1207 stack,
1208 missing_type.and_then(|t| TupleAttrs::attr_from_type(t)),
1209 );
1210 }
1211 if cur > offset || cur + self.buf.len() < offset {
1212 return (stack, None);
1213 }
1214 let mut attrs = self.clone();
1215 let mut last_off = cur + attrs.pos;
1216 let mut missing = None;
1217 while let Some(attr) = attrs.next() {
1218 let Ok(attr) = attr else { break };
1219 match attr {
1220 TupleAttrs::TupleIp(val) => {
1221 (stack, missing) = val.lookup_attr(offset, missing_type);
1222 if !stack.is_empty() {
1223 break;
1224 }
1225 }
1226 TupleAttrs::TupleProto(val) => {
1227 (stack, missing) = val.lookup_attr(offset, missing_type);
1228 if !stack.is_empty() {
1229 break;
1230 }
1231 }
1232 TupleAttrs::TupleZone(val) => {
1233 if last_off == offset {
1234 stack.push(("TupleZone", last_off));
1235 break;
1236 }
1237 }
1238 _ => {}
1239 };
1240 last_off = cur + attrs.pos;
1241 }
1242 if !stack.is_empty() {
1243 stack.push(("TupleAttrs", cur));
1244 }
1245 (stack, missing)
1246 }
1247}
1248#[derive(Clone)]
1249pub enum ProtoinfoTcpAttrs {
1250 #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
1251 TcpState(u8),
1252 #[doc = "window scaling factor in original direction"]
1253 TcpWscaleOriginal(u8),
1254 #[doc = "window scaling factor in reply direction"]
1255 TcpWscaleReply(u8),
1256 TcpFlagsOriginal(PushNfCtTcpFlagsMask),
1257 TcpFlagsReply(PushNfCtTcpFlagsMask),
1258}
1259impl<'a> IterableProtoinfoTcpAttrs<'a> {
1260 #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
1261 pub fn get_tcp_state(&self) -> Result<u8, ErrorContext> {
1262 let mut iter = self.clone();
1263 iter.pos = 0;
1264 for attr in iter {
1265 if let ProtoinfoTcpAttrs::TcpState(val) = attr? {
1266 return Ok(val);
1267 }
1268 }
1269 Err(ErrorContext::new_missing(
1270 "ProtoinfoTcpAttrs",
1271 "TcpState",
1272 self.orig_loc,
1273 self.buf.as_ptr() as usize,
1274 ))
1275 }
1276 #[doc = "window scaling factor in original direction"]
1277 pub fn get_tcp_wscale_original(&self) -> Result<u8, ErrorContext> {
1278 let mut iter = self.clone();
1279 iter.pos = 0;
1280 for attr in iter {
1281 if let ProtoinfoTcpAttrs::TcpWscaleOriginal(val) = attr? {
1282 return Ok(val);
1283 }
1284 }
1285 Err(ErrorContext::new_missing(
1286 "ProtoinfoTcpAttrs",
1287 "TcpWscaleOriginal",
1288 self.orig_loc,
1289 self.buf.as_ptr() as usize,
1290 ))
1291 }
1292 #[doc = "window scaling factor in reply direction"]
1293 pub fn get_tcp_wscale_reply(&self) -> Result<u8, ErrorContext> {
1294 let mut iter = self.clone();
1295 iter.pos = 0;
1296 for attr in iter {
1297 if let ProtoinfoTcpAttrs::TcpWscaleReply(val) = attr? {
1298 return Ok(val);
1299 }
1300 }
1301 Err(ErrorContext::new_missing(
1302 "ProtoinfoTcpAttrs",
1303 "TcpWscaleReply",
1304 self.orig_loc,
1305 self.buf.as_ptr() as usize,
1306 ))
1307 }
1308 pub fn get_tcp_flags_original(&self) -> Result<PushNfCtTcpFlagsMask, ErrorContext> {
1309 let mut iter = self.clone();
1310 iter.pos = 0;
1311 for attr in iter {
1312 if let ProtoinfoTcpAttrs::TcpFlagsOriginal(val) = attr? {
1313 return Ok(val);
1314 }
1315 }
1316 Err(ErrorContext::new_missing(
1317 "ProtoinfoTcpAttrs",
1318 "TcpFlagsOriginal",
1319 self.orig_loc,
1320 self.buf.as_ptr() as usize,
1321 ))
1322 }
1323 pub fn get_tcp_flags_reply(&self) -> Result<PushNfCtTcpFlagsMask, ErrorContext> {
1324 let mut iter = self.clone();
1325 iter.pos = 0;
1326 for attr in iter {
1327 if let ProtoinfoTcpAttrs::TcpFlagsReply(val) = attr? {
1328 return Ok(val);
1329 }
1330 }
1331 Err(ErrorContext::new_missing(
1332 "ProtoinfoTcpAttrs",
1333 "TcpFlagsReply",
1334 self.orig_loc,
1335 self.buf.as_ptr() as usize,
1336 ))
1337 }
1338}
1339impl ProtoinfoTcpAttrs {
1340 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoTcpAttrs<'a> {
1341 IterableProtoinfoTcpAttrs::with_loc(buf, buf.as_ptr() as usize)
1342 }
1343 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1344 let res = match r#type {
1345 1u16 => "TcpState",
1346 2u16 => "TcpWscaleOriginal",
1347 3u16 => "TcpWscaleReply",
1348 4u16 => "TcpFlagsOriginal",
1349 5u16 => "TcpFlagsReply",
1350 _ => return None,
1351 };
1352 Some(res)
1353 }
1354}
1355#[derive(Clone, Copy, Default)]
1356pub struct IterableProtoinfoTcpAttrs<'a> {
1357 buf: &'a [u8],
1358 pos: usize,
1359 orig_loc: usize,
1360}
1361impl<'a> IterableProtoinfoTcpAttrs<'a> {
1362 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1363 Self {
1364 buf,
1365 pos: 0,
1366 orig_loc,
1367 }
1368 }
1369 pub fn get_buf(&self) -> &'a [u8] {
1370 self.buf
1371 }
1372}
1373impl<'a> Iterator for IterableProtoinfoTcpAttrs<'a> {
1374 type Item = Result<ProtoinfoTcpAttrs, ErrorContext>;
1375 fn next(&mut self) -> Option<Self::Item> {
1376 let pos = self.pos;
1377 let mut r#type;
1378 loop {
1379 r#type = None;
1380 if self.buf.len() == self.pos {
1381 return None;
1382 }
1383 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1384 break;
1385 };
1386 r#type = Some(header.r#type);
1387 let res = match header.r#type {
1388 1u16 => ProtoinfoTcpAttrs::TcpState({
1389 let res = parse_u8(next);
1390 let Some(val) = res else { break };
1391 val
1392 }),
1393 2u16 => ProtoinfoTcpAttrs::TcpWscaleOriginal({
1394 let res = parse_u8(next);
1395 let Some(val) = res else { break };
1396 val
1397 }),
1398 3u16 => ProtoinfoTcpAttrs::TcpWscaleReply({
1399 let res = parse_u8(next);
1400 let Some(val) = res else { break };
1401 val
1402 }),
1403 4u16 => ProtoinfoTcpAttrs::TcpFlagsOriginal({
1404 let res = PushNfCtTcpFlagsMask::new_from_slice(next);
1405 let Some(val) = res else { break };
1406 val
1407 }),
1408 5u16 => ProtoinfoTcpAttrs::TcpFlagsReply({
1409 let res = PushNfCtTcpFlagsMask::new_from_slice(next);
1410 let Some(val) = res else { break };
1411 val
1412 }),
1413 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1414 n => continue,
1415 };
1416 return Some(Ok(res));
1417 }
1418 Some(Err(ErrorContext::new(
1419 "ProtoinfoTcpAttrs",
1420 r#type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1421 self.orig_loc,
1422 self.buf.as_ptr().wrapping_add(pos) as usize,
1423 )))
1424 }
1425}
1426impl std::fmt::Debug for IterableProtoinfoTcpAttrs<'_> {
1427 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1428 let mut fmt = f.debug_struct("ProtoinfoTcpAttrs");
1429 for attr in self.clone() {
1430 let attr = match attr {
1431 Ok(a) => a,
1432 Err(err) => {
1433 fmt.finish()?;
1434 f.write_str("Err(")?;
1435 err.fmt(f)?;
1436 return f.write_str(")");
1437 }
1438 };
1439 match attr {
1440 ProtoinfoTcpAttrs::TcpState(val) => fmt.field(
1441 "TcpState",
1442 &FormatEnum(val.into(), NfCtTcpState::from_value),
1443 ),
1444 ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => fmt.field("TcpWscaleOriginal", &val),
1445 ProtoinfoTcpAttrs::TcpWscaleReply(val) => fmt.field("TcpWscaleReply", &val),
1446 ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => fmt.field("TcpFlagsOriginal", &val),
1447 ProtoinfoTcpAttrs::TcpFlagsReply(val) => fmt.field("TcpFlagsReply", &val),
1448 };
1449 }
1450 fmt.finish()
1451 }
1452}
1453impl IterableProtoinfoTcpAttrs<'_> {
1454 pub fn lookup_attr(
1455 &self,
1456 offset: usize,
1457 missing_type: Option<u16>,
1458 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1459 let mut stack = Vec::new();
1460 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1461 if cur == offset {
1462 stack.push(("ProtoinfoTcpAttrs", offset));
1463 return (
1464 stack,
1465 missing_type.and_then(|t| ProtoinfoTcpAttrs::attr_from_type(t)),
1466 );
1467 }
1468 if cur > offset || cur + self.buf.len() < offset {
1469 return (stack, None);
1470 }
1471 let mut attrs = self.clone();
1472 let mut last_off = cur + attrs.pos;
1473 while let Some(attr) = attrs.next() {
1474 let Ok(attr) = attr else { break };
1475 match attr {
1476 ProtoinfoTcpAttrs::TcpState(val) => {
1477 if last_off == offset {
1478 stack.push(("TcpState", last_off));
1479 break;
1480 }
1481 }
1482 ProtoinfoTcpAttrs::TcpWscaleOriginal(val) => {
1483 if last_off == offset {
1484 stack.push(("TcpWscaleOriginal", last_off));
1485 break;
1486 }
1487 }
1488 ProtoinfoTcpAttrs::TcpWscaleReply(val) => {
1489 if last_off == offset {
1490 stack.push(("TcpWscaleReply", last_off));
1491 break;
1492 }
1493 }
1494 ProtoinfoTcpAttrs::TcpFlagsOriginal(val) => {
1495 if last_off == offset {
1496 stack.push(("TcpFlagsOriginal", last_off));
1497 break;
1498 }
1499 }
1500 ProtoinfoTcpAttrs::TcpFlagsReply(val) => {
1501 if last_off == offset {
1502 stack.push(("TcpFlagsReply", last_off));
1503 break;
1504 }
1505 }
1506 _ => {}
1507 };
1508 last_off = cur + attrs.pos;
1509 }
1510 if !stack.is_empty() {
1511 stack.push(("ProtoinfoTcpAttrs", cur));
1512 }
1513 (stack, None)
1514 }
1515}
1516#[derive(Clone)]
1517pub enum ProtoinfoDccpAttrs<'a> {
1518 #[doc = "dccp connection state"]
1519 DccpState(u8),
1520 DccpRole(u8),
1521 DccpHandshakeSeq(u64),
1522 DccpPad(&'a [u8]),
1523}
1524impl<'a> IterableProtoinfoDccpAttrs<'a> {
1525 #[doc = "dccp connection state"]
1526 pub fn get_dccp_state(&self) -> Result<u8, ErrorContext> {
1527 let mut iter = self.clone();
1528 iter.pos = 0;
1529 for attr in iter {
1530 if let ProtoinfoDccpAttrs::DccpState(val) = attr? {
1531 return Ok(val);
1532 }
1533 }
1534 Err(ErrorContext::new_missing(
1535 "ProtoinfoDccpAttrs",
1536 "DccpState",
1537 self.orig_loc,
1538 self.buf.as_ptr() as usize,
1539 ))
1540 }
1541 pub fn get_dccp_role(&self) -> Result<u8, ErrorContext> {
1542 let mut iter = self.clone();
1543 iter.pos = 0;
1544 for attr in iter {
1545 if let ProtoinfoDccpAttrs::DccpRole(val) = attr? {
1546 return Ok(val);
1547 }
1548 }
1549 Err(ErrorContext::new_missing(
1550 "ProtoinfoDccpAttrs",
1551 "DccpRole",
1552 self.orig_loc,
1553 self.buf.as_ptr() as usize,
1554 ))
1555 }
1556 pub fn get_dccp_handshake_seq(&self) -> Result<u64, ErrorContext> {
1557 let mut iter = self.clone();
1558 iter.pos = 0;
1559 for attr in iter {
1560 if let ProtoinfoDccpAttrs::DccpHandshakeSeq(val) = attr? {
1561 return Ok(val);
1562 }
1563 }
1564 Err(ErrorContext::new_missing(
1565 "ProtoinfoDccpAttrs",
1566 "DccpHandshakeSeq",
1567 self.orig_loc,
1568 self.buf.as_ptr() as usize,
1569 ))
1570 }
1571 pub fn get_dccp_pad(&self) -> Result<&'a [u8], ErrorContext> {
1572 let mut iter = self.clone();
1573 iter.pos = 0;
1574 for attr in iter {
1575 if let ProtoinfoDccpAttrs::DccpPad(val) = attr? {
1576 return Ok(val);
1577 }
1578 }
1579 Err(ErrorContext::new_missing(
1580 "ProtoinfoDccpAttrs",
1581 "DccpPad",
1582 self.orig_loc,
1583 self.buf.as_ptr() as usize,
1584 ))
1585 }
1586}
1587impl ProtoinfoDccpAttrs<'_> {
1588 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoDccpAttrs<'a> {
1589 IterableProtoinfoDccpAttrs::with_loc(buf, buf.as_ptr() as usize)
1590 }
1591 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1592 let res = match r#type {
1593 1u16 => "DccpState",
1594 2u16 => "DccpRole",
1595 3u16 => "DccpHandshakeSeq",
1596 4u16 => "DccpPad",
1597 _ => return None,
1598 };
1599 Some(res)
1600 }
1601}
1602#[derive(Clone, Copy, Default)]
1603pub struct IterableProtoinfoDccpAttrs<'a> {
1604 buf: &'a [u8],
1605 pos: usize,
1606 orig_loc: usize,
1607}
1608impl<'a> IterableProtoinfoDccpAttrs<'a> {
1609 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1610 Self {
1611 buf,
1612 pos: 0,
1613 orig_loc,
1614 }
1615 }
1616 pub fn get_buf(&self) -> &'a [u8] {
1617 self.buf
1618 }
1619}
1620impl<'a> Iterator for IterableProtoinfoDccpAttrs<'a> {
1621 type Item = Result<ProtoinfoDccpAttrs<'a>, ErrorContext>;
1622 fn next(&mut self) -> Option<Self::Item> {
1623 let pos = self.pos;
1624 let mut r#type;
1625 loop {
1626 r#type = None;
1627 if self.buf.len() == self.pos {
1628 return None;
1629 }
1630 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1631 break;
1632 };
1633 r#type = Some(header.r#type);
1634 let res = match header.r#type {
1635 1u16 => ProtoinfoDccpAttrs::DccpState({
1636 let res = parse_u8(next);
1637 let Some(val) = res else { break };
1638 val
1639 }),
1640 2u16 => ProtoinfoDccpAttrs::DccpRole({
1641 let res = parse_u8(next);
1642 let Some(val) = res else { break };
1643 val
1644 }),
1645 3u16 => ProtoinfoDccpAttrs::DccpHandshakeSeq({
1646 let res = parse_be_u64(next);
1647 let Some(val) = res else { break };
1648 val
1649 }),
1650 4u16 => ProtoinfoDccpAttrs::DccpPad({
1651 let res = Some(next);
1652 let Some(val) = res else { break };
1653 val
1654 }),
1655 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1656 n => continue,
1657 };
1658 return Some(Ok(res));
1659 }
1660 Some(Err(ErrorContext::new(
1661 "ProtoinfoDccpAttrs",
1662 r#type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1663 self.orig_loc,
1664 self.buf.as_ptr().wrapping_add(pos) as usize,
1665 )))
1666 }
1667}
1668impl<'a> std::fmt::Debug for IterableProtoinfoDccpAttrs<'_> {
1669 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1670 let mut fmt = f.debug_struct("ProtoinfoDccpAttrs");
1671 for attr in self.clone() {
1672 let attr = match attr {
1673 Ok(a) => a,
1674 Err(err) => {
1675 fmt.finish()?;
1676 f.write_str("Err(")?;
1677 err.fmt(f)?;
1678 return f.write_str(")");
1679 }
1680 };
1681 match attr {
1682 ProtoinfoDccpAttrs::DccpState(val) => fmt.field("DccpState", &val),
1683 ProtoinfoDccpAttrs::DccpRole(val) => fmt.field("DccpRole", &val),
1684 ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => fmt.field("DccpHandshakeSeq", &val),
1685 ProtoinfoDccpAttrs::DccpPad(val) => fmt.field("DccpPad", &val),
1686 };
1687 }
1688 fmt.finish()
1689 }
1690}
1691impl IterableProtoinfoDccpAttrs<'_> {
1692 pub fn lookup_attr(
1693 &self,
1694 offset: usize,
1695 missing_type: Option<u16>,
1696 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1697 let mut stack = Vec::new();
1698 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1699 if cur == offset {
1700 stack.push(("ProtoinfoDccpAttrs", offset));
1701 return (
1702 stack,
1703 missing_type.and_then(|t| ProtoinfoDccpAttrs::attr_from_type(t)),
1704 );
1705 }
1706 if cur > offset || cur + self.buf.len() < offset {
1707 return (stack, None);
1708 }
1709 let mut attrs = self.clone();
1710 let mut last_off = cur + attrs.pos;
1711 while let Some(attr) = attrs.next() {
1712 let Ok(attr) = attr else { break };
1713 match attr {
1714 ProtoinfoDccpAttrs::DccpState(val) => {
1715 if last_off == offset {
1716 stack.push(("DccpState", last_off));
1717 break;
1718 }
1719 }
1720 ProtoinfoDccpAttrs::DccpRole(val) => {
1721 if last_off == offset {
1722 stack.push(("DccpRole", last_off));
1723 break;
1724 }
1725 }
1726 ProtoinfoDccpAttrs::DccpHandshakeSeq(val) => {
1727 if last_off == offset {
1728 stack.push(("DccpHandshakeSeq", last_off));
1729 break;
1730 }
1731 }
1732 ProtoinfoDccpAttrs::DccpPad(val) => {
1733 if last_off == offset {
1734 stack.push(("DccpPad", last_off));
1735 break;
1736 }
1737 }
1738 _ => {}
1739 };
1740 last_off = cur + attrs.pos;
1741 }
1742 if !stack.is_empty() {
1743 stack.push(("ProtoinfoDccpAttrs", cur));
1744 }
1745 (stack, None)
1746 }
1747}
1748#[derive(Clone)]
1749pub enum ProtoinfoSctpAttrs {
1750 #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
1751 SctpState(u8),
1752 VtagOriginal(u32),
1753 VtagReply(u32),
1754}
1755impl<'a> IterableProtoinfoSctpAttrs<'a> {
1756 #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
1757 pub fn get_sctp_state(&self) -> Result<u8, ErrorContext> {
1758 let mut iter = self.clone();
1759 iter.pos = 0;
1760 for attr in iter {
1761 if let ProtoinfoSctpAttrs::SctpState(val) = attr? {
1762 return Ok(val);
1763 }
1764 }
1765 Err(ErrorContext::new_missing(
1766 "ProtoinfoSctpAttrs",
1767 "SctpState",
1768 self.orig_loc,
1769 self.buf.as_ptr() as usize,
1770 ))
1771 }
1772 pub fn get_vtag_original(&self) -> Result<u32, ErrorContext> {
1773 let mut iter = self.clone();
1774 iter.pos = 0;
1775 for attr in iter {
1776 if let ProtoinfoSctpAttrs::VtagOriginal(val) = attr? {
1777 return Ok(val);
1778 }
1779 }
1780 Err(ErrorContext::new_missing(
1781 "ProtoinfoSctpAttrs",
1782 "VtagOriginal",
1783 self.orig_loc,
1784 self.buf.as_ptr() as usize,
1785 ))
1786 }
1787 pub fn get_vtag_reply(&self) -> Result<u32, ErrorContext> {
1788 let mut iter = self.clone();
1789 iter.pos = 0;
1790 for attr in iter {
1791 if let ProtoinfoSctpAttrs::VtagReply(val) = attr? {
1792 return Ok(val);
1793 }
1794 }
1795 Err(ErrorContext::new_missing(
1796 "ProtoinfoSctpAttrs",
1797 "VtagReply",
1798 self.orig_loc,
1799 self.buf.as_ptr() as usize,
1800 ))
1801 }
1802}
1803impl ProtoinfoSctpAttrs {
1804 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoSctpAttrs<'a> {
1805 IterableProtoinfoSctpAttrs::with_loc(buf, buf.as_ptr() as usize)
1806 }
1807 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1808 let res = match r#type {
1809 1u16 => "SctpState",
1810 2u16 => "VtagOriginal",
1811 3u16 => "VtagReply",
1812 _ => return None,
1813 };
1814 Some(res)
1815 }
1816}
1817#[derive(Clone, Copy, Default)]
1818pub struct IterableProtoinfoSctpAttrs<'a> {
1819 buf: &'a [u8],
1820 pos: usize,
1821 orig_loc: usize,
1822}
1823impl<'a> IterableProtoinfoSctpAttrs<'a> {
1824 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1825 Self {
1826 buf,
1827 pos: 0,
1828 orig_loc,
1829 }
1830 }
1831 pub fn get_buf(&self) -> &'a [u8] {
1832 self.buf
1833 }
1834}
1835impl<'a> Iterator for IterableProtoinfoSctpAttrs<'a> {
1836 type Item = Result<ProtoinfoSctpAttrs, ErrorContext>;
1837 fn next(&mut self) -> Option<Self::Item> {
1838 let pos = self.pos;
1839 let mut r#type;
1840 loop {
1841 r#type = None;
1842 if self.buf.len() == self.pos {
1843 return None;
1844 }
1845 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1846 break;
1847 };
1848 r#type = Some(header.r#type);
1849 let res = match header.r#type {
1850 1u16 => ProtoinfoSctpAttrs::SctpState({
1851 let res = parse_u8(next);
1852 let Some(val) = res else { break };
1853 val
1854 }),
1855 2u16 => ProtoinfoSctpAttrs::VtagOriginal({
1856 let res = parse_be_u32(next);
1857 let Some(val) = res else { break };
1858 val
1859 }),
1860 3u16 => ProtoinfoSctpAttrs::VtagReply({
1861 let res = parse_be_u32(next);
1862 let Some(val) = res else { break };
1863 val
1864 }),
1865 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1866 n => continue,
1867 };
1868 return Some(Ok(res));
1869 }
1870 Some(Err(ErrorContext::new(
1871 "ProtoinfoSctpAttrs",
1872 r#type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
1873 self.orig_loc,
1874 self.buf.as_ptr().wrapping_add(pos) as usize,
1875 )))
1876 }
1877}
1878impl std::fmt::Debug for IterableProtoinfoSctpAttrs<'_> {
1879 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1880 let mut fmt = f.debug_struct("ProtoinfoSctpAttrs");
1881 for attr in self.clone() {
1882 let attr = match attr {
1883 Ok(a) => a,
1884 Err(err) => {
1885 fmt.finish()?;
1886 f.write_str("Err(")?;
1887 err.fmt(f)?;
1888 return f.write_str(")");
1889 }
1890 };
1891 match attr {
1892 ProtoinfoSctpAttrs::SctpState(val) => fmt.field(
1893 "SctpState",
1894 &FormatEnum(val.into(), NfCtSctpState::from_value),
1895 ),
1896 ProtoinfoSctpAttrs::VtagOriginal(val) => fmt.field("VtagOriginal", &val),
1897 ProtoinfoSctpAttrs::VtagReply(val) => fmt.field("VtagReply", &val),
1898 };
1899 }
1900 fmt.finish()
1901 }
1902}
1903impl IterableProtoinfoSctpAttrs<'_> {
1904 pub fn lookup_attr(
1905 &self,
1906 offset: usize,
1907 missing_type: Option<u16>,
1908 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1909 let mut stack = Vec::new();
1910 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1911 if cur == offset {
1912 stack.push(("ProtoinfoSctpAttrs", offset));
1913 return (
1914 stack,
1915 missing_type.and_then(|t| ProtoinfoSctpAttrs::attr_from_type(t)),
1916 );
1917 }
1918 if cur > offset || cur + self.buf.len() < offset {
1919 return (stack, None);
1920 }
1921 let mut attrs = self.clone();
1922 let mut last_off = cur + attrs.pos;
1923 while let Some(attr) = attrs.next() {
1924 let Ok(attr) = attr else { break };
1925 match attr {
1926 ProtoinfoSctpAttrs::SctpState(val) => {
1927 if last_off == offset {
1928 stack.push(("SctpState", last_off));
1929 break;
1930 }
1931 }
1932 ProtoinfoSctpAttrs::VtagOriginal(val) => {
1933 if last_off == offset {
1934 stack.push(("VtagOriginal", last_off));
1935 break;
1936 }
1937 }
1938 ProtoinfoSctpAttrs::VtagReply(val) => {
1939 if last_off == offset {
1940 stack.push(("VtagReply", last_off));
1941 break;
1942 }
1943 }
1944 _ => {}
1945 };
1946 last_off = cur + attrs.pos;
1947 }
1948 if !stack.is_empty() {
1949 stack.push(("ProtoinfoSctpAttrs", cur));
1950 }
1951 (stack, None)
1952 }
1953}
1954#[derive(Clone)]
1955pub enum ProtoinfoAttrs<'a> {
1956 #[doc = "conntrack tcp state information"]
1957 ProtoinfoTcp(IterableProtoinfoTcpAttrs<'a>),
1958 #[doc = "conntrack dccp state information"]
1959 ProtoinfoDccp(IterableProtoinfoDccpAttrs<'a>),
1960 #[doc = "conntrack sctp state information"]
1961 ProtoinfoSctp(IterableProtoinfoSctpAttrs<'a>),
1962}
1963impl<'a> IterableProtoinfoAttrs<'a> {
1964 #[doc = "conntrack tcp state information"]
1965 pub fn get_protoinfo_tcp(&self) -> Result<IterableProtoinfoTcpAttrs<'a>, ErrorContext> {
1966 let mut iter = self.clone();
1967 iter.pos = 0;
1968 for attr in iter {
1969 if let ProtoinfoAttrs::ProtoinfoTcp(val) = attr? {
1970 return Ok(val);
1971 }
1972 }
1973 Err(ErrorContext::new_missing(
1974 "ProtoinfoAttrs",
1975 "ProtoinfoTcp",
1976 self.orig_loc,
1977 self.buf.as_ptr() as usize,
1978 ))
1979 }
1980 #[doc = "conntrack dccp state information"]
1981 pub fn get_protoinfo_dccp(&self) -> Result<IterableProtoinfoDccpAttrs<'a>, ErrorContext> {
1982 let mut iter = self.clone();
1983 iter.pos = 0;
1984 for attr in iter {
1985 if let ProtoinfoAttrs::ProtoinfoDccp(val) = attr? {
1986 return Ok(val);
1987 }
1988 }
1989 Err(ErrorContext::new_missing(
1990 "ProtoinfoAttrs",
1991 "ProtoinfoDccp",
1992 self.orig_loc,
1993 self.buf.as_ptr() as usize,
1994 ))
1995 }
1996 #[doc = "conntrack sctp state information"]
1997 pub fn get_protoinfo_sctp(&self) -> Result<IterableProtoinfoSctpAttrs<'a>, ErrorContext> {
1998 let mut iter = self.clone();
1999 iter.pos = 0;
2000 for attr in iter {
2001 if let ProtoinfoAttrs::ProtoinfoSctp(val) = attr? {
2002 return Ok(val);
2003 }
2004 }
2005 Err(ErrorContext::new_missing(
2006 "ProtoinfoAttrs",
2007 "ProtoinfoSctp",
2008 self.orig_loc,
2009 self.buf.as_ptr() as usize,
2010 ))
2011 }
2012}
2013impl ProtoinfoAttrs<'_> {
2014 pub fn new<'a>(buf: &'a [u8]) -> IterableProtoinfoAttrs<'a> {
2015 IterableProtoinfoAttrs::with_loc(buf, buf.as_ptr() as usize)
2016 }
2017 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2018 let res = match r#type {
2019 1u16 => "ProtoinfoTcp",
2020 2u16 => "ProtoinfoDccp",
2021 3u16 => "ProtoinfoSctp",
2022 _ => return None,
2023 };
2024 Some(res)
2025 }
2026}
2027#[derive(Clone, Copy, Default)]
2028pub struct IterableProtoinfoAttrs<'a> {
2029 buf: &'a [u8],
2030 pos: usize,
2031 orig_loc: usize,
2032}
2033impl<'a> IterableProtoinfoAttrs<'a> {
2034 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2035 Self {
2036 buf,
2037 pos: 0,
2038 orig_loc,
2039 }
2040 }
2041 pub fn get_buf(&self) -> &'a [u8] {
2042 self.buf
2043 }
2044}
2045impl<'a> Iterator for IterableProtoinfoAttrs<'a> {
2046 type Item = Result<ProtoinfoAttrs<'a>, ErrorContext>;
2047 fn next(&mut self) -> Option<Self::Item> {
2048 let pos = self.pos;
2049 let mut r#type;
2050 loop {
2051 r#type = None;
2052 if self.buf.len() == self.pos {
2053 return None;
2054 }
2055 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2056 break;
2057 };
2058 r#type = Some(header.r#type);
2059 let res = match header.r#type {
2060 1u16 => ProtoinfoAttrs::ProtoinfoTcp({
2061 let res = Some(IterableProtoinfoTcpAttrs::with_loc(next, self.orig_loc));
2062 let Some(val) = res else { break };
2063 val
2064 }),
2065 2u16 => ProtoinfoAttrs::ProtoinfoDccp({
2066 let res = Some(IterableProtoinfoDccpAttrs::with_loc(next, self.orig_loc));
2067 let Some(val) = res else { break };
2068 val
2069 }),
2070 3u16 => ProtoinfoAttrs::ProtoinfoSctp({
2071 let res = Some(IterableProtoinfoSctpAttrs::with_loc(next, self.orig_loc));
2072 let Some(val) = res else { break };
2073 val
2074 }),
2075 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2076 n => continue,
2077 };
2078 return Some(Ok(res));
2079 }
2080 Some(Err(ErrorContext::new(
2081 "ProtoinfoAttrs",
2082 r#type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2083 self.orig_loc,
2084 self.buf.as_ptr().wrapping_add(pos) as usize,
2085 )))
2086 }
2087}
2088impl<'a> std::fmt::Debug for IterableProtoinfoAttrs<'_> {
2089 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2090 let mut fmt = f.debug_struct("ProtoinfoAttrs");
2091 for attr in self.clone() {
2092 let attr = match attr {
2093 Ok(a) => a,
2094 Err(err) => {
2095 fmt.finish()?;
2096 f.write_str("Err(")?;
2097 err.fmt(f)?;
2098 return f.write_str(")");
2099 }
2100 };
2101 match attr {
2102 ProtoinfoAttrs::ProtoinfoTcp(val) => fmt.field("ProtoinfoTcp", &val),
2103 ProtoinfoAttrs::ProtoinfoDccp(val) => fmt.field("ProtoinfoDccp", &val),
2104 ProtoinfoAttrs::ProtoinfoSctp(val) => fmt.field("ProtoinfoSctp", &val),
2105 };
2106 }
2107 fmt.finish()
2108 }
2109}
2110impl IterableProtoinfoAttrs<'_> {
2111 pub fn lookup_attr(
2112 &self,
2113 offset: usize,
2114 missing_type: Option<u16>,
2115 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2116 let mut stack = Vec::new();
2117 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2118 if cur == offset {
2119 stack.push(("ProtoinfoAttrs", offset));
2120 return (
2121 stack,
2122 missing_type.and_then(|t| ProtoinfoAttrs::attr_from_type(t)),
2123 );
2124 }
2125 if cur > offset || cur + self.buf.len() < offset {
2126 return (stack, None);
2127 }
2128 let mut attrs = self.clone();
2129 let mut last_off = cur + attrs.pos;
2130 let mut missing = None;
2131 while let Some(attr) = attrs.next() {
2132 let Ok(attr) = attr else { break };
2133 match attr {
2134 ProtoinfoAttrs::ProtoinfoTcp(val) => {
2135 (stack, missing) = val.lookup_attr(offset, missing_type);
2136 if !stack.is_empty() {
2137 break;
2138 }
2139 }
2140 ProtoinfoAttrs::ProtoinfoDccp(val) => {
2141 (stack, missing) = val.lookup_attr(offset, missing_type);
2142 if !stack.is_empty() {
2143 break;
2144 }
2145 }
2146 ProtoinfoAttrs::ProtoinfoSctp(val) => {
2147 (stack, missing) = val.lookup_attr(offset, missing_type);
2148 if !stack.is_empty() {
2149 break;
2150 }
2151 }
2152 _ => {}
2153 };
2154 last_off = cur + attrs.pos;
2155 }
2156 if !stack.is_empty() {
2157 stack.push(("ProtoinfoAttrs", cur));
2158 }
2159 (stack, missing)
2160 }
2161}
2162#[derive(Clone)]
2163pub enum HelpAttrs<'a> {
2164 #[doc = "helper name"]
2165 HelpName(&'a CStr),
2166}
2167impl<'a> IterableHelpAttrs<'a> {
2168 #[doc = "helper name"]
2169 pub fn get_help_name(&self) -> Result<&'a CStr, ErrorContext> {
2170 let mut iter = self.clone();
2171 iter.pos = 0;
2172 for attr in iter {
2173 if let HelpAttrs::HelpName(val) = attr? {
2174 return Ok(val);
2175 }
2176 }
2177 Err(ErrorContext::new_missing(
2178 "HelpAttrs",
2179 "HelpName",
2180 self.orig_loc,
2181 self.buf.as_ptr() as usize,
2182 ))
2183 }
2184}
2185impl HelpAttrs<'_> {
2186 pub fn new<'a>(buf: &'a [u8]) -> IterableHelpAttrs<'a> {
2187 IterableHelpAttrs::with_loc(buf, buf.as_ptr() as usize)
2188 }
2189 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2190 let res = match r#type {
2191 1u16 => "HelpName",
2192 _ => return None,
2193 };
2194 Some(res)
2195 }
2196}
2197#[derive(Clone, Copy, Default)]
2198pub struct IterableHelpAttrs<'a> {
2199 buf: &'a [u8],
2200 pos: usize,
2201 orig_loc: usize,
2202}
2203impl<'a> IterableHelpAttrs<'a> {
2204 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2205 Self {
2206 buf,
2207 pos: 0,
2208 orig_loc,
2209 }
2210 }
2211 pub fn get_buf(&self) -> &'a [u8] {
2212 self.buf
2213 }
2214}
2215impl<'a> Iterator for IterableHelpAttrs<'a> {
2216 type Item = Result<HelpAttrs<'a>, ErrorContext>;
2217 fn next(&mut self) -> Option<Self::Item> {
2218 let pos = self.pos;
2219 let mut r#type;
2220 loop {
2221 r#type = None;
2222 if self.buf.len() == self.pos {
2223 return None;
2224 }
2225 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2226 break;
2227 };
2228 r#type = Some(header.r#type);
2229 let res = match header.r#type {
2230 1u16 => HelpAttrs::HelpName({
2231 let res = CStr::from_bytes_with_nul(next).ok();
2232 let Some(val) = res else { break };
2233 val
2234 }),
2235 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2236 n => continue,
2237 };
2238 return Some(Ok(res));
2239 }
2240 Some(Err(ErrorContext::new(
2241 "HelpAttrs",
2242 r#type.and_then(|t| HelpAttrs::attr_from_type(t)),
2243 self.orig_loc,
2244 self.buf.as_ptr().wrapping_add(pos) as usize,
2245 )))
2246 }
2247}
2248impl<'a> std::fmt::Debug for IterableHelpAttrs<'_> {
2249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2250 let mut fmt = f.debug_struct("HelpAttrs");
2251 for attr in self.clone() {
2252 let attr = match attr {
2253 Ok(a) => a,
2254 Err(err) => {
2255 fmt.finish()?;
2256 f.write_str("Err(")?;
2257 err.fmt(f)?;
2258 return f.write_str(")");
2259 }
2260 };
2261 match attr {
2262 HelpAttrs::HelpName(val) => fmt.field("HelpName", &val),
2263 };
2264 }
2265 fmt.finish()
2266 }
2267}
2268impl IterableHelpAttrs<'_> {
2269 pub fn lookup_attr(
2270 &self,
2271 offset: usize,
2272 missing_type: Option<u16>,
2273 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2274 let mut stack = Vec::new();
2275 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2276 if cur == offset {
2277 stack.push(("HelpAttrs", offset));
2278 return (
2279 stack,
2280 missing_type.and_then(|t| HelpAttrs::attr_from_type(t)),
2281 );
2282 }
2283 if cur > offset || cur + self.buf.len() < offset {
2284 return (stack, None);
2285 }
2286 let mut attrs = self.clone();
2287 let mut last_off = cur + attrs.pos;
2288 while let Some(attr) = attrs.next() {
2289 let Ok(attr) = attr else { break };
2290 match attr {
2291 HelpAttrs::HelpName(val) => {
2292 if last_off == offset {
2293 stack.push(("HelpName", last_off));
2294 break;
2295 }
2296 }
2297 _ => {}
2298 };
2299 last_off = cur + attrs.pos;
2300 }
2301 if !stack.is_empty() {
2302 stack.push(("HelpAttrs", cur));
2303 }
2304 (stack, None)
2305 }
2306}
2307#[derive(Clone)]
2308pub enum NatProtoAttrs {
2309 NatPortMin(u16),
2310 NatPortMax(u16),
2311}
2312impl<'a> IterableNatProtoAttrs<'a> {
2313 pub fn get_nat_port_min(&self) -> Result<u16, ErrorContext> {
2314 let mut iter = self.clone();
2315 iter.pos = 0;
2316 for attr in iter {
2317 if let NatProtoAttrs::NatPortMin(val) = attr? {
2318 return Ok(val);
2319 }
2320 }
2321 Err(ErrorContext::new_missing(
2322 "NatProtoAttrs",
2323 "NatPortMin",
2324 self.orig_loc,
2325 self.buf.as_ptr() as usize,
2326 ))
2327 }
2328 pub fn get_nat_port_max(&self) -> Result<u16, ErrorContext> {
2329 let mut iter = self.clone();
2330 iter.pos = 0;
2331 for attr in iter {
2332 if let NatProtoAttrs::NatPortMax(val) = attr? {
2333 return Ok(val);
2334 }
2335 }
2336 Err(ErrorContext::new_missing(
2337 "NatProtoAttrs",
2338 "NatPortMax",
2339 self.orig_loc,
2340 self.buf.as_ptr() as usize,
2341 ))
2342 }
2343}
2344impl NatProtoAttrs {
2345 pub fn new<'a>(buf: &'a [u8]) -> IterableNatProtoAttrs<'a> {
2346 IterableNatProtoAttrs::with_loc(buf, buf.as_ptr() as usize)
2347 }
2348 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2349 let res = match r#type {
2350 1u16 => "NatPortMin",
2351 2u16 => "NatPortMax",
2352 _ => return None,
2353 };
2354 Some(res)
2355 }
2356}
2357#[derive(Clone, Copy, Default)]
2358pub struct IterableNatProtoAttrs<'a> {
2359 buf: &'a [u8],
2360 pos: usize,
2361 orig_loc: usize,
2362}
2363impl<'a> IterableNatProtoAttrs<'a> {
2364 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2365 Self {
2366 buf,
2367 pos: 0,
2368 orig_loc,
2369 }
2370 }
2371 pub fn get_buf(&self) -> &'a [u8] {
2372 self.buf
2373 }
2374}
2375impl<'a> Iterator for IterableNatProtoAttrs<'a> {
2376 type Item = Result<NatProtoAttrs, ErrorContext>;
2377 fn next(&mut self) -> Option<Self::Item> {
2378 let pos = self.pos;
2379 let mut r#type;
2380 loop {
2381 r#type = None;
2382 if self.buf.len() == self.pos {
2383 return None;
2384 }
2385 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2386 break;
2387 };
2388 r#type = Some(header.r#type);
2389 let res = match header.r#type {
2390 1u16 => NatProtoAttrs::NatPortMin({
2391 let res = parse_be_u16(next);
2392 let Some(val) = res else { break };
2393 val
2394 }),
2395 2u16 => NatProtoAttrs::NatPortMax({
2396 let res = parse_be_u16(next);
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 "NatProtoAttrs",
2407 r#type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2408 self.orig_loc,
2409 self.buf.as_ptr().wrapping_add(pos) as usize,
2410 )))
2411 }
2412}
2413impl std::fmt::Debug for IterableNatProtoAttrs<'_> {
2414 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2415 let mut fmt = f.debug_struct("NatProtoAttrs");
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 NatProtoAttrs::NatPortMin(val) => fmt.field("NatPortMin", &val),
2428 NatProtoAttrs::NatPortMax(val) => fmt.field("NatPortMax", &val),
2429 };
2430 }
2431 fmt.finish()
2432 }
2433}
2434impl IterableNatProtoAttrs<'_> {
2435 pub fn lookup_attr(
2436 &self,
2437 offset: usize,
2438 missing_type: Option<u16>,
2439 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2440 let mut stack = Vec::new();
2441 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2442 if cur == offset {
2443 stack.push(("NatProtoAttrs", offset));
2444 return (
2445 stack,
2446 missing_type.and_then(|t| NatProtoAttrs::attr_from_type(t)),
2447 );
2448 }
2449 if cur > offset || cur + self.buf.len() < offset {
2450 return (stack, None);
2451 }
2452 let mut attrs = self.clone();
2453 let mut last_off = cur + attrs.pos;
2454 while let Some(attr) = attrs.next() {
2455 let Ok(attr) = attr else { break };
2456 match attr {
2457 NatProtoAttrs::NatPortMin(val) => {
2458 if last_off == offset {
2459 stack.push(("NatPortMin", last_off));
2460 break;
2461 }
2462 }
2463 NatProtoAttrs::NatPortMax(val) => {
2464 if last_off == offset {
2465 stack.push(("NatPortMax", last_off));
2466 break;
2467 }
2468 }
2469 _ => {}
2470 };
2471 last_off = cur + attrs.pos;
2472 }
2473 if !stack.is_empty() {
2474 stack.push(("NatProtoAttrs", cur));
2475 }
2476 (stack, None)
2477 }
2478}
2479#[derive(Clone)]
2480pub enum NatAttrs<'a> {
2481 NatV4Minip(u32),
2482 NatV4Maxip(u32),
2483 NatV6Minip(&'a [u8]),
2484 NatV6Maxip(&'a [u8]),
2485 NatProto(IterableNatProtoAttrs<'a>),
2486}
2487impl<'a> IterableNatAttrs<'a> {
2488 pub fn get_nat_v4_minip(&self) -> Result<u32, ErrorContext> {
2489 let mut iter = self.clone();
2490 iter.pos = 0;
2491 for attr in iter {
2492 if let NatAttrs::NatV4Minip(val) = attr? {
2493 return Ok(val);
2494 }
2495 }
2496 Err(ErrorContext::new_missing(
2497 "NatAttrs",
2498 "NatV4Minip",
2499 self.orig_loc,
2500 self.buf.as_ptr() as usize,
2501 ))
2502 }
2503 pub fn get_nat_v4_maxip(&self) -> Result<u32, ErrorContext> {
2504 let mut iter = self.clone();
2505 iter.pos = 0;
2506 for attr in iter {
2507 if let NatAttrs::NatV4Maxip(val) = attr? {
2508 return Ok(val);
2509 }
2510 }
2511 Err(ErrorContext::new_missing(
2512 "NatAttrs",
2513 "NatV4Maxip",
2514 self.orig_loc,
2515 self.buf.as_ptr() as usize,
2516 ))
2517 }
2518 pub fn get_nat_v6_minip(&self) -> Result<&'a [u8], ErrorContext> {
2519 let mut iter = self.clone();
2520 iter.pos = 0;
2521 for attr in iter {
2522 if let NatAttrs::NatV6Minip(val) = attr? {
2523 return Ok(val);
2524 }
2525 }
2526 Err(ErrorContext::new_missing(
2527 "NatAttrs",
2528 "NatV6Minip",
2529 self.orig_loc,
2530 self.buf.as_ptr() as usize,
2531 ))
2532 }
2533 pub fn get_nat_v6_maxip(&self) -> Result<&'a [u8], ErrorContext> {
2534 let mut iter = self.clone();
2535 iter.pos = 0;
2536 for attr in iter {
2537 if let NatAttrs::NatV6Maxip(val) = attr? {
2538 return Ok(val);
2539 }
2540 }
2541 Err(ErrorContext::new_missing(
2542 "NatAttrs",
2543 "NatV6Maxip",
2544 self.orig_loc,
2545 self.buf.as_ptr() as usize,
2546 ))
2547 }
2548 pub fn get_nat_proto(&self) -> Result<IterableNatProtoAttrs<'a>, ErrorContext> {
2549 let mut iter = self.clone();
2550 iter.pos = 0;
2551 for attr in iter {
2552 if let NatAttrs::NatProto(val) = attr? {
2553 return Ok(val);
2554 }
2555 }
2556 Err(ErrorContext::new_missing(
2557 "NatAttrs",
2558 "NatProto",
2559 self.orig_loc,
2560 self.buf.as_ptr() as usize,
2561 ))
2562 }
2563}
2564impl NatAttrs<'_> {
2565 pub fn new<'a>(buf: &'a [u8]) -> IterableNatAttrs<'a> {
2566 IterableNatAttrs::with_loc(buf, buf.as_ptr() as usize)
2567 }
2568 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2569 let res = match r#type {
2570 1u16 => "NatV4Minip",
2571 2u16 => "NatV4Maxip",
2572 3u16 => "NatV6Minip",
2573 4u16 => "NatV6Maxip",
2574 5u16 => "NatProto",
2575 _ => return None,
2576 };
2577 Some(res)
2578 }
2579}
2580#[derive(Clone, Copy, Default)]
2581pub struct IterableNatAttrs<'a> {
2582 buf: &'a [u8],
2583 pos: usize,
2584 orig_loc: usize,
2585}
2586impl<'a> IterableNatAttrs<'a> {
2587 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2588 Self {
2589 buf,
2590 pos: 0,
2591 orig_loc,
2592 }
2593 }
2594 pub fn get_buf(&self) -> &'a [u8] {
2595 self.buf
2596 }
2597}
2598impl<'a> Iterator for IterableNatAttrs<'a> {
2599 type Item = Result<NatAttrs<'a>, ErrorContext>;
2600 fn next(&mut self) -> Option<Self::Item> {
2601 let pos = self.pos;
2602 let mut r#type;
2603 loop {
2604 r#type = None;
2605 if self.buf.len() == self.pos {
2606 return None;
2607 }
2608 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2609 break;
2610 };
2611 r#type = Some(header.r#type);
2612 let res = match header.r#type {
2613 1u16 => NatAttrs::NatV4Minip({
2614 let res = parse_be_u32(next);
2615 let Some(val) = res else { break };
2616 val
2617 }),
2618 2u16 => NatAttrs::NatV4Maxip({
2619 let res = parse_be_u32(next);
2620 let Some(val) = res else { break };
2621 val
2622 }),
2623 3u16 => NatAttrs::NatV6Minip({
2624 let res = Some(next);
2625 let Some(val) = res else { break };
2626 val
2627 }),
2628 4u16 => NatAttrs::NatV6Maxip({
2629 let res = Some(next);
2630 let Some(val) = res else { break };
2631 val
2632 }),
2633 5u16 => NatAttrs::NatProto({
2634 let res = Some(IterableNatProtoAttrs::with_loc(next, self.orig_loc));
2635 let Some(val) = res else { break };
2636 val
2637 }),
2638 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2639 n => continue,
2640 };
2641 return Some(Ok(res));
2642 }
2643 Some(Err(ErrorContext::new(
2644 "NatAttrs",
2645 r#type.and_then(|t| NatAttrs::attr_from_type(t)),
2646 self.orig_loc,
2647 self.buf.as_ptr().wrapping_add(pos) as usize,
2648 )))
2649 }
2650}
2651impl<'a> std::fmt::Debug for IterableNatAttrs<'_> {
2652 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2653 let mut fmt = f.debug_struct("NatAttrs");
2654 for attr in self.clone() {
2655 let attr = match attr {
2656 Ok(a) => a,
2657 Err(err) => {
2658 fmt.finish()?;
2659 f.write_str("Err(")?;
2660 err.fmt(f)?;
2661 return f.write_str(")");
2662 }
2663 };
2664 match attr {
2665 NatAttrs::NatV4Minip(val) => fmt.field("NatV4Minip", &val),
2666 NatAttrs::NatV4Maxip(val) => fmt.field("NatV4Maxip", &val),
2667 NatAttrs::NatV6Minip(val) => fmt.field("NatV6Minip", &val),
2668 NatAttrs::NatV6Maxip(val) => fmt.field("NatV6Maxip", &val),
2669 NatAttrs::NatProto(val) => fmt.field("NatProto", &val),
2670 };
2671 }
2672 fmt.finish()
2673 }
2674}
2675impl IterableNatAttrs<'_> {
2676 pub fn lookup_attr(
2677 &self,
2678 offset: usize,
2679 missing_type: Option<u16>,
2680 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2681 let mut stack = Vec::new();
2682 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2683 if cur == offset {
2684 stack.push(("NatAttrs", offset));
2685 return (
2686 stack,
2687 missing_type.and_then(|t| NatAttrs::attr_from_type(t)),
2688 );
2689 }
2690 if cur > offset || cur + self.buf.len() < offset {
2691 return (stack, None);
2692 }
2693 let mut attrs = self.clone();
2694 let mut last_off = cur + attrs.pos;
2695 let mut missing = None;
2696 while let Some(attr) = attrs.next() {
2697 let Ok(attr) = attr else { break };
2698 match attr {
2699 NatAttrs::NatV4Minip(val) => {
2700 if last_off == offset {
2701 stack.push(("NatV4Minip", last_off));
2702 break;
2703 }
2704 }
2705 NatAttrs::NatV4Maxip(val) => {
2706 if last_off == offset {
2707 stack.push(("NatV4Maxip", last_off));
2708 break;
2709 }
2710 }
2711 NatAttrs::NatV6Minip(val) => {
2712 if last_off == offset {
2713 stack.push(("NatV6Minip", last_off));
2714 break;
2715 }
2716 }
2717 NatAttrs::NatV6Maxip(val) => {
2718 if last_off == offset {
2719 stack.push(("NatV6Maxip", last_off));
2720 break;
2721 }
2722 }
2723 NatAttrs::NatProto(val) => {
2724 (stack, missing) = val.lookup_attr(offset, missing_type);
2725 if !stack.is_empty() {
2726 break;
2727 }
2728 }
2729 _ => {}
2730 };
2731 last_off = cur + attrs.pos;
2732 }
2733 if !stack.is_empty() {
2734 stack.push(("NatAttrs", cur));
2735 }
2736 (stack, missing)
2737 }
2738}
2739#[derive(Clone)]
2740pub enum SeqadjAttrs {
2741 CorrectionPos(u32),
2742 OffsetBefore(u32),
2743 OffsetAfter(u32),
2744}
2745impl<'a> IterableSeqadjAttrs<'a> {
2746 pub fn get_correction_pos(&self) -> Result<u32, ErrorContext> {
2747 let mut iter = self.clone();
2748 iter.pos = 0;
2749 for attr in iter {
2750 if let SeqadjAttrs::CorrectionPos(val) = attr? {
2751 return Ok(val);
2752 }
2753 }
2754 Err(ErrorContext::new_missing(
2755 "SeqadjAttrs",
2756 "CorrectionPos",
2757 self.orig_loc,
2758 self.buf.as_ptr() as usize,
2759 ))
2760 }
2761 pub fn get_offset_before(&self) -> Result<u32, ErrorContext> {
2762 let mut iter = self.clone();
2763 iter.pos = 0;
2764 for attr in iter {
2765 if let SeqadjAttrs::OffsetBefore(val) = attr? {
2766 return Ok(val);
2767 }
2768 }
2769 Err(ErrorContext::new_missing(
2770 "SeqadjAttrs",
2771 "OffsetBefore",
2772 self.orig_loc,
2773 self.buf.as_ptr() as usize,
2774 ))
2775 }
2776 pub fn get_offset_after(&self) -> Result<u32, ErrorContext> {
2777 let mut iter = self.clone();
2778 iter.pos = 0;
2779 for attr in iter {
2780 if let SeqadjAttrs::OffsetAfter(val) = attr? {
2781 return Ok(val);
2782 }
2783 }
2784 Err(ErrorContext::new_missing(
2785 "SeqadjAttrs",
2786 "OffsetAfter",
2787 self.orig_loc,
2788 self.buf.as_ptr() as usize,
2789 ))
2790 }
2791}
2792impl SeqadjAttrs {
2793 pub fn new<'a>(buf: &'a [u8]) -> IterableSeqadjAttrs<'a> {
2794 IterableSeqadjAttrs::with_loc(buf, buf.as_ptr() as usize)
2795 }
2796 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2797 let res = match r#type {
2798 1u16 => "CorrectionPos",
2799 2u16 => "OffsetBefore",
2800 3u16 => "OffsetAfter",
2801 _ => return None,
2802 };
2803 Some(res)
2804 }
2805}
2806#[derive(Clone, Copy, Default)]
2807pub struct IterableSeqadjAttrs<'a> {
2808 buf: &'a [u8],
2809 pos: usize,
2810 orig_loc: usize,
2811}
2812impl<'a> IterableSeqadjAttrs<'a> {
2813 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2814 Self {
2815 buf,
2816 pos: 0,
2817 orig_loc,
2818 }
2819 }
2820 pub fn get_buf(&self) -> &'a [u8] {
2821 self.buf
2822 }
2823}
2824impl<'a> Iterator for IterableSeqadjAttrs<'a> {
2825 type Item = Result<SeqadjAttrs, ErrorContext>;
2826 fn next(&mut self) -> Option<Self::Item> {
2827 let pos = self.pos;
2828 let mut r#type;
2829 loop {
2830 r#type = None;
2831 if self.buf.len() == self.pos {
2832 return None;
2833 }
2834 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2835 break;
2836 };
2837 r#type = Some(header.r#type);
2838 let res = match header.r#type {
2839 1u16 => SeqadjAttrs::CorrectionPos({
2840 let res = parse_be_u32(next);
2841 let Some(val) = res else { break };
2842 val
2843 }),
2844 2u16 => SeqadjAttrs::OffsetBefore({
2845 let res = parse_be_u32(next);
2846 let Some(val) = res else { break };
2847 val
2848 }),
2849 3u16 => SeqadjAttrs::OffsetAfter({
2850 let res = parse_be_u32(next);
2851 let Some(val) = res else { break };
2852 val
2853 }),
2854 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2855 n => continue,
2856 };
2857 return Some(Ok(res));
2858 }
2859 Some(Err(ErrorContext::new(
2860 "SeqadjAttrs",
2861 r#type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
2862 self.orig_loc,
2863 self.buf.as_ptr().wrapping_add(pos) as usize,
2864 )))
2865 }
2866}
2867impl std::fmt::Debug for IterableSeqadjAttrs<'_> {
2868 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2869 let mut fmt = f.debug_struct("SeqadjAttrs");
2870 for attr in self.clone() {
2871 let attr = match attr {
2872 Ok(a) => a,
2873 Err(err) => {
2874 fmt.finish()?;
2875 f.write_str("Err(")?;
2876 err.fmt(f)?;
2877 return f.write_str(")");
2878 }
2879 };
2880 match attr {
2881 SeqadjAttrs::CorrectionPos(val) => fmt.field("CorrectionPos", &val),
2882 SeqadjAttrs::OffsetBefore(val) => fmt.field("OffsetBefore", &val),
2883 SeqadjAttrs::OffsetAfter(val) => fmt.field("OffsetAfter", &val),
2884 };
2885 }
2886 fmt.finish()
2887 }
2888}
2889impl IterableSeqadjAttrs<'_> {
2890 pub fn lookup_attr(
2891 &self,
2892 offset: usize,
2893 missing_type: Option<u16>,
2894 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2895 let mut stack = Vec::new();
2896 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2897 if cur == offset {
2898 stack.push(("SeqadjAttrs", offset));
2899 return (
2900 stack,
2901 missing_type.and_then(|t| SeqadjAttrs::attr_from_type(t)),
2902 );
2903 }
2904 if cur > offset || cur + self.buf.len() < offset {
2905 return (stack, None);
2906 }
2907 let mut attrs = self.clone();
2908 let mut last_off = cur + attrs.pos;
2909 while let Some(attr) = attrs.next() {
2910 let Ok(attr) = attr else { break };
2911 match attr {
2912 SeqadjAttrs::CorrectionPos(val) => {
2913 if last_off == offset {
2914 stack.push(("CorrectionPos", last_off));
2915 break;
2916 }
2917 }
2918 SeqadjAttrs::OffsetBefore(val) => {
2919 if last_off == offset {
2920 stack.push(("OffsetBefore", last_off));
2921 break;
2922 }
2923 }
2924 SeqadjAttrs::OffsetAfter(val) => {
2925 if last_off == offset {
2926 stack.push(("OffsetAfter", last_off));
2927 break;
2928 }
2929 }
2930 _ => {}
2931 };
2932 last_off = cur + attrs.pos;
2933 }
2934 if !stack.is_empty() {
2935 stack.push(("SeqadjAttrs", cur));
2936 }
2937 (stack, None)
2938 }
2939}
2940#[derive(Clone)]
2941pub enum SecctxAttrs<'a> {
2942 SecctxName(&'a CStr),
2943}
2944impl<'a> IterableSecctxAttrs<'a> {
2945 pub fn get_secctx_name(&self) -> Result<&'a CStr, ErrorContext> {
2946 let mut iter = self.clone();
2947 iter.pos = 0;
2948 for attr in iter {
2949 if let SecctxAttrs::SecctxName(val) = attr? {
2950 return Ok(val);
2951 }
2952 }
2953 Err(ErrorContext::new_missing(
2954 "SecctxAttrs",
2955 "SecctxName",
2956 self.orig_loc,
2957 self.buf.as_ptr() as usize,
2958 ))
2959 }
2960}
2961impl SecctxAttrs<'_> {
2962 pub fn new<'a>(buf: &'a [u8]) -> IterableSecctxAttrs<'a> {
2963 IterableSecctxAttrs::with_loc(buf, buf.as_ptr() as usize)
2964 }
2965 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2966 let res = match r#type {
2967 1u16 => "SecctxName",
2968 _ => return None,
2969 };
2970 Some(res)
2971 }
2972}
2973#[derive(Clone, Copy, Default)]
2974pub struct IterableSecctxAttrs<'a> {
2975 buf: &'a [u8],
2976 pos: usize,
2977 orig_loc: usize,
2978}
2979impl<'a> IterableSecctxAttrs<'a> {
2980 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2981 Self {
2982 buf,
2983 pos: 0,
2984 orig_loc,
2985 }
2986 }
2987 pub fn get_buf(&self) -> &'a [u8] {
2988 self.buf
2989 }
2990}
2991impl<'a> Iterator for IterableSecctxAttrs<'a> {
2992 type Item = Result<SecctxAttrs<'a>, ErrorContext>;
2993 fn next(&mut self) -> Option<Self::Item> {
2994 let pos = self.pos;
2995 let mut r#type;
2996 loop {
2997 r#type = None;
2998 if self.buf.len() == self.pos {
2999 return None;
3000 }
3001 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3002 break;
3003 };
3004 r#type = Some(header.r#type);
3005 let res = match header.r#type {
3006 1u16 => SecctxAttrs::SecctxName({
3007 let res = CStr::from_bytes_with_nul(next).ok();
3008 let Some(val) = res else { break };
3009 val
3010 }),
3011 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3012 n => continue,
3013 };
3014 return Some(Ok(res));
3015 }
3016 Some(Err(ErrorContext::new(
3017 "SecctxAttrs",
3018 r#type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3019 self.orig_loc,
3020 self.buf.as_ptr().wrapping_add(pos) as usize,
3021 )))
3022 }
3023}
3024impl<'a> std::fmt::Debug for IterableSecctxAttrs<'_> {
3025 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3026 let mut fmt = f.debug_struct("SecctxAttrs");
3027 for attr in self.clone() {
3028 let attr = match attr {
3029 Ok(a) => a,
3030 Err(err) => {
3031 fmt.finish()?;
3032 f.write_str("Err(")?;
3033 err.fmt(f)?;
3034 return f.write_str(")");
3035 }
3036 };
3037 match attr {
3038 SecctxAttrs::SecctxName(val) => fmt.field("SecctxName", &val),
3039 };
3040 }
3041 fmt.finish()
3042 }
3043}
3044impl IterableSecctxAttrs<'_> {
3045 pub fn lookup_attr(
3046 &self,
3047 offset: usize,
3048 missing_type: Option<u16>,
3049 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3050 let mut stack = Vec::new();
3051 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3052 if cur == offset {
3053 stack.push(("SecctxAttrs", offset));
3054 return (
3055 stack,
3056 missing_type.and_then(|t| SecctxAttrs::attr_from_type(t)),
3057 );
3058 }
3059 if cur > offset || cur + self.buf.len() < offset {
3060 return (stack, None);
3061 }
3062 let mut attrs = self.clone();
3063 let mut last_off = cur + attrs.pos;
3064 while let Some(attr) = attrs.next() {
3065 let Ok(attr) = attr else { break };
3066 match attr {
3067 SecctxAttrs::SecctxName(val) => {
3068 if last_off == offset {
3069 stack.push(("SecctxName", last_off));
3070 break;
3071 }
3072 }
3073 _ => {}
3074 };
3075 last_off = cur + attrs.pos;
3076 }
3077 if !stack.is_empty() {
3078 stack.push(("SecctxAttrs", cur));
3079 }
3080 (stack, None)
3081 }
3082}
3083#[derive(Clone)]
3084pub enum SynproxyAttrs {
3085 Isn(u32),
3086 Its(u32),
3087 Tsoff(u32),
3088}
3089impl<'a> IterableSynproxyAttrs<'a> {
3090 pub fn get_isn(&self) -> Result<u32, ErrorContext> {
3091 let mut iter = self.clone();
3092 iter.pos = 0;
3093 for attr in iter {
3094 if let SynproxyAttrs::Isn(val) = attr? {
3095 return Ok(val);
3096 }
3097 }
3098 Err(ErrorContext::new_missing(
3099 "SynproxyAttrs",
3100 "Isn",
3101 self.orig_loc,
3102 self.buf.as_ptr() as usize,
3103 ))
3104 }
3105 pub fn get_its(&self) -> Result<u32, ErrorContext> {
3106 let mut iter = self.clone();
3107 iter.pos = 0;
3108 for attr in iter {
3109 if let SynproxyAttrs::Its(val) = attr? {
3110 return Ok(val);
3111 }
3112 }
3113 Err(ErrorContext::new_missing(
3114 "SynproxyAttrs",
3115 "Its",
3116 self.orig_loc,
3117 self.buf.as_ptr() as usize,
3118 ))
3119 }
3120 pub fn get_tsoff(&self) -> Result<u32, ErrorContext> {
3121 let mut iter = self.clone();
3122 iter.pos = 0;
3123 for attr in iter {
3124 if let SynproxyAttrs::Tsoff(val) = attr? {
3125 return Ok(val);
3126 }
3127 }
3128 Err(ErrorContext::new_missing(
3129 "SynproxyAttrs",
3130 "Tsoff",
3131 self.orig_loc,
3132 self.buf.as_ptr() as usize,
3133 ))
3134 }
3135}
3136impl SynproxyAttrs {
3137 pub fn new<'a>(buf: &'a [u8]) -> IterableSynproxyAttrs<'a> {
3138 IterableSynproxyAttrs::with_loc(buf, buf.as_ptr() as usize)
3139 }
3140 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3141 let res = match r#type {
3142 1u16 => "Isn",
3143 2u16 => "Its",
3144 3u16 => "Tsoff",
3145 _ => return None,
3146 };
3147 Some(res)
3148 }
3149}
3150#[derive(Clone, Copy, Default)]
3151pub struct IterableSynproxyAttrs<'a> {
3152 buf: &'a [u8],
3153 pos: usize,
3154 orig_loc: usize,
3155}
3156impl<'a> IterableSynproxyAttrs<'a> {
3157 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3158 Self {
3159 buf,
3160 pos: 0,
3161 orig_loc,
3162 }
3163 }
3164 pub fn get_buf(&self) -> &'a [u8] {
3165 self.buf
3166 }
3167}
3168impl<'a> Iterator for IterableSynproxyAttrs<'a> {
3169 type Item = Result<SynproxyAttrs, ErrorContext>;
3170 fn next(&mut self) -> Option<Self::Item> {
3171 let pos = self.pos;
3172 let mut r#type;
3173 loop {
3174 r#type = None;
3175 if self.buf.len() == self.pos {
3176 return None;
3177 }
3178 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3179 break;
3180 };
3181 r#type = Some(header.r#type);
3182 let res = match header.r#type {
3183 1u16 => SynproxyAttrs::Isn({
3184 let res = parse_be_u32(next);
3185 let Some(val) = res else { break };
3186 val
3187 }),
3188 2u16 => SynproxyAttrs::Its({
3189 let res = parse_be_u32(next);
3190 let Some(val) = res else { break };
3191 val
3192 }),
3193 3u16 => SynproxyAttrs::Tsoff({
3194 let res = parse_be_u32(next);
3195 let Some(val) = res else { break };
3196 val
3197 }),
3198 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3199 n => continue,
3200 };
3201 return Some(Ok(res));
3202 }
3203 Some(Err(ErrorContext::new(
3204 "SynproxyAttrs",
3205 r#type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3206 self.orig_loc,
3207 self.buf.as_ptr().wrapping_add(pos) as usize,
3208 )))
3209 }
3210}
3211impl std::fmt::Debug for IterableSynproxyAttrs<'_> {
3212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3213 let mut fmt = f.debug_struct("SynproxyAttrs");
3214 for attr in self.clone() {
3215 let attr = match attr {
3216 Ok(a) => a,
3217 Err(err) => {
3218 fmt.finish()?;
3219 f.write_str("Err(")?;
3220 err.fmt(f)?;
3221 return f.write_str(")");
3222 }
3223 };
3224 match attr {
3225 SynproxyAttrs::Isn(val) => fmt.field("Isn", &val),
3226 SynproxyAttrs::Its(val) => fmt.field("Its", &val),
3227 SynproxyAttrs::Tsoff(val) => fmt.field("Tsoff", &val),
3228 };
3229 }
3230 fmt.finish()
3231 }
3232}
3233impl IterableSynproxyAttrs<'_> {
3234 pub fn lookup_attr(
3235 &self,
3236 offset: usize,
3237 missing_type: Option<u16>,
3238 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3239 let mut stack = Vec::new();
3240 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3241 if cur == offset {
3242 stack.push(("SynproxyAttrs", offset));
3243 return (
3244 stack,
3245 missing_type.and_then(|t| SynproxyAttrs::attr_from_type(t)),
3246 );
3247 }
3248 if cur > offset || cur + self.buf.len() < offset {
3249 return (stack, None);
3250 }
3251 let mut attrs = self.clone();
3252 let mut last_off = cur + attrs.pos;
3253 while let Some(attr) = attrs.next() {
3254 let Ok(attr) = attr else { break };
3255 match attr {
3256 SynproxyAttrs::Isn(val) => {
3257 if last_off == offset {
3258 stack.push(("Isn", last_off));
3259 break;
3260 }
3261 }
3262 SynproxyAttrs::Its(val) => {
3263 if last_off == offset {
3264 stack.push(("Its", last_off));
3265 break;
3266 }
3267 }
3268 SynproxyAttrs::Tsoff(val) => {
3269 if last_off == offset {
3270 stack.push(("Tsoff", last_off));
3271 break;
3272 }
3273 }
3274 _ => {}
3275 };
3276 last_off = cur + attrs.pos;
3277 }
3278 if !stack.is_empty() {
3279 stack.push(("SynproxyAttrs", cur));
3280 }
3281 (stack, None)
3282 }
3283}
3284#[derive(Clone)]
3285pub enum ConntrackAttrs<'a> {
3286 #[doc = "conntrack l3+l4 protocol information, original direction"]
3287 TupleOrig(IterableTupleAttrs<'a>),
3288 #[doc = "conntrack l3+l4 protocol information, reply direction"]
3289 TupleReply(IterableTupleAttrs<'a>),
3290 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3291 Status(u32),
3292 Protoinfo(IterableProtoinfoAttrs<'a>),
3293 Help(IterableHelpAttrs<'a>),
3294 NatSrc(IterableNatAttrs<'a>),
3295 Timeout(u32),
3296 Mark(u32),
3297 CountersOrig(IterableCounterAttrs<'a>),
3298 CountersReply(IterableCounterAttrs<'a>),
3299 Use(u32),
3300 Id(u32),
3301 NatDst(IterableNatAttrs<'a>),
3302 TupleMaster(IterableTupleAttrs<'a>),
3303 SeqAdjOrig(IterableSeqadjAttrs<'a>),
3304 SeqAdjReply(IterableSeqadjAttrs<'a>),
3305 #[doc = "obsolete"]
3306 Secmark(&'a [u8]),
3307 #[doc = "conntrack zone id"]
3308 Zone(u16),
3309 Secctx(IterableSecctxAttrs<'a>),
3310 Timestamp(u64),
3311 MarkMask(u32),
3312 Labels(&'a [u8]),
3313 LabelsMask(&'a [u8]),
3314 Synproxy(IterableSynproxyAttrs<'a>),
3315 Filter(IterableTupleAttrs<'a>),
3316 #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3317 StatusMask(u32),
3318 TimestampEvent(u64),
3319}
3320impl<'a> IterableConntrackAttrs<'a> {
3321 #[doc = "conntrack l3+l4 protocol information, original direction"]
3322 pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3323 let mut iter = self.clone();
3324 iter.pos = 0;
3325 for attr in iter {
3326 if let ConntrackAttrs::TupleOrig(val) = attr? {
3327 return Ok(val);
3328 }
3329 }
3330 Err(ErrorContext::new_missing(
3331 "ConntrackAttrs",
3332 "TupleOrig",
3333 self.orig_loc,
3334 self.buf.as_ptr() as usize,
3335 ))
3336 }
3337 #[doc = "conntrack l3+l4 protocol information, reply direction"]
3338 pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3339 let mut iter = self.clone();
3340 iter.pos = 0;
3341 for attr in iter {
3342 if let ConntrackAttrs::TupleReply(val) = attr? {
3343 return Ok(val);
3344 }
3345 }
3346 Err(ErrorContext::new_missing(
3347 "ConntrackAttrs",
3348 "TupleReply",
3349 self.orig_loc,
3350 self.buf.as_ptr() as usize,
3351 ))
3352 }
3353 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3354 pub fn get_status(&self) -> Result<u32, ErrorContext> {
3355 let mut iter = self.clone();
3356 iter.pos = 0;
3357 for attr in iter {
3358 if let ConntrackAttrs::Status(val) = attr? {
3359 return Ok(val);
3360 }
3361 }
3362 Err(ErrorContext::new_missing(
3363 "ConntrackAttrs",
3364 "Status",
3365 self.orig_loc,
3366 self.buf.as_ptr() as usize,
3367 ))
3368 }
3369 pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
3370 let mut iter = self.clone();
3371 iter.pos = 0;
3372 for attr in iter {
3373 if let ConntrackAttrs::Protoinfo(val) = attr? {
3374 return Ok(val);
3375 }
3376 }
3377 Err(ErrorContext::new_missing(
3378 "ConntrackAttrs",
3379 "Protoinfo",
3380 self.orig_loc,
3381 self.buf.as_ptr() as usize,
3382 ))
3383 }
3384 pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
3385 let mut iter = self.clone();
3386 iter.pos = 0;
3387 for attr in iter {
3388 if let ConntrackAttrs::Help(val) = attr? {
3389 return Ok(val);
3390 }
3391 }
3392 Err(ErrorContext::new_missing(
3393 "ConntrackAttrs",
3394 "Help",
3395 self.orig_loc,
3396 self.buf.as_ptr() as usize,
3397 ))
3398 }
3399 pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3400 let mut iter = self.clone();
3401 iter.pos = 0;
3402 for attr in iter {
3403 if let ConntrackAttrs::NatSrc(val) = attr? {
3404 return Ok(val);
3405 }
3406 }
3407 Err(ErrorContext::new_missing(
3408 "ConntrackAttrs",
3409 "NatSrc",
3410 self.orig_loc,
3411 self.buf.as_ptr() as usize,
3412 ))
3413 }
3414 pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
3415 let mut iter = self.clone();
3416 iter.pos = 0;
3417 for attr in iter {
3418 if let ConntrackAttrs::Timeout(val) = attr? {
3419 return Ok(val);
3420 }
3421 }
3422 Err(ErrorContext::new_missing(
3423 "ConntrackAttrs",
3424 "Timeout",
3425 self.orig_loc,
3426 self.buf.as_ptr() as usize,
3427 ))
3428 }
3429 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
3430 let mut iter = self.clone();
3431 iter.pos = 0;
3432 for attr in iter {
3433 if let ConntrackAttrs::Mark(val) = attr? {
3434 return Ok(val);
3435 }
3436 }
3437 Err(ErrorContext::new_missing(
3438 "ConntrackAttrs",
3439 "Mark",
3440 self.orig_loc,
3441 self.buf.as_ptr() as usize,
3442 ))
3443 }
3444 pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3445 let mut iter = self.clone();
3446 iter.pos = 0;
3447 for attr in iter {
3448 if let ConntrackAttrs::CountersOrig(val) = attr? {
3449 return Ok(val);
3450 }
3451 }
3452 Err(ErrorContext::new_missing(
3453 "ConntrackAttrs",
3454 "CountersOrig",
3455 self.orig_loc,
3456 self.buf.as_ptr() as usize,
3457 ))
3458 }
3459 pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
3460 let mut iter = self.clone();
3461 iter.pos = 0;
3462 for attr in iter {
3463 if let ConntrackAttrs::CountersReply(val) = attr? {
3464 return Ok(val);
3465 }
3466 }
3467 Err(ErrorContext::new_missing(
3468 "ConntrackAttrs",
3469 "CountersReply",
3470 self.orig_loc,
3471 self.buf.as_ptr() as usize,
3472 ))
3473 }
3474 pub fn get_use(&self) -> Result<u32, ErrorContext> {
3475 let mut iter = self.clone();
3476 iter.pos = 0;
3477 for attr in iter {
3478 if let ConntrackAttrs::Use(val) = attr? {
3479 return Ok(val);
3480 }
3481 }
3482 Err(ErrorContext::new_missing(
3483 "ConntrackAttrs",
3484 "Use",
3485 self.orig_loc,
3486 self.buf.as_ptr() as usize,
3487 ))
3488 }
3489 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3490 let mut iter = self.clone();
3491 iter.pos = 0;
3492 for attr in iter {
3493 if let ConntrackAttrs::Id(val) = attr? {
3494 return Ok(val);
3495 }
3496 }
3497 Err(ErrorContext::new_missing(
3498 "ConntrackAttrs",
3499 "Id",
3500 self.orig_loc,
3501 self.buf.as_ptr() as usize,
3502 ))
3503 }
3504 pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
3505 let mut iter = self.clone();
3506 iter.pos = 0;
3507 for attr in iter {
3508 if let ConntrackAttrs::NatDst(val) = attr? {
3509 return Ok(val);
3510 }
3511 }
3512 Err(ErrorContext::new_missing(
3513 "ConntrackAttrs",
3514 "NatDst",
3515 self.orig_loc,
3516 self.buf.as_ptr() as usize,
3517 ))
3518 }
3519 pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3520 let mut iter = self.clone();
3521 iter.pos = 0;
3522 for attr in iter {
3523 if let ConntrackAttrs::TupleMaster(val) = attr? {
3524 return Ok(val);
3525 }
3526 }
3527 Err(ErrorContext::new_missing(
3528 "ConntrackAttrs",
3529 "TupleMaster",
3530 self.orig_loc,
3531 self.buf.as_ptr() as usize,
3532 ))
3533 }
3534 pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3535 let mut iter = self.clone();
3536 iter.pos = 0;
3537 for attr in iter {
3538 if let ConntrackAttrs::SeqAdjOrig(val) = attr? {
3539 return Ok(val);
3540 }
3541 }
3542 Err(ErrorContext::new_missing(
3543 "ConntrackAttrs",
3544 "SeqAdjOrig",
3545 self.orig_loc,
3546 self.buf.as_ptr() as usize,
3547 ))
3548 }
3549 pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
3550 let mut iter = self.clone();
3551 iter.pos = 0;
3552 for attr in iter {
3553 if let ConntrackAttrs::SeqAdjReply(val) = attr? {
3554 return Ok(val);
3555 }
3556 }
3557 Err(ErrorContext::new_missing(
3558 "ConntrackAttrs",
3559 "SeqAdjReply",
3560 self.orig_loc,
3561 self.buf.as_ptr() as usize,
3562 ))
3563 }
3564 #[doc = "obsolete"]
3565 pub fn get_secmark(&self) -> Result<&'a [u8], ErrorContext> {
3566 let mut iter = self.clone();
3567 iter.pos = 0;
3568 for attr in iter {
3569 if let ConntrackAttrs::Secmark(val) = attr? {
3570 return Ok(val);
3571 }
3572 }
3573 Err(ErrorContext::new_missing(
3574 "ConntrackAttrs",
3575 "Secmark",
3576 self.orig_loc,
3577 self.buf.as_ptr() as usize,
3578 ))
3579 }
3580 #[doc = "conntrack zone id"]
3581 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
3582 let mut iter = self.clone();
3583 iter.pos = 0;
3584 for attr in iter {
3585 if let ConntrackAttrs::Zone(val) = attr? {
3586 return Ok(val);
3587 }
3588 }
3589 Err(ErrorContext::new_missing(
3590 "ConntrackAttrs",
3591 "Zone",
3592 self.orig_loc,
3593 self.buf.as_ptr() as usize,
3594 ))
3595 }
3596 pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
3597 let mut iter = self.clone();
3598 iter.pos = 0;
3599 for attr in iter {
3600 if let ConntrackAttrs::Secctx(val) = attr? {
3601 return Ok(val);
3602 }
3603 }
3604 Err(ErrorContext::new_missing(
3605 "ConntrackAttrs",
3606 "Secctx",
3607 self.orig_loc,
3608 self.buf.as_ptr() as usize,
3609 ))
3610 }
3611 pub fn get_timestamp(&self) -> Result<u64, ErrorContext> {
3612 let mut iter = self.clone();
3613 iter.pos = 0;
3614 for attr in iter {
3615 if let ConntrackAttrs::Timestamp(val) = attr? {
3616 return Ok(val);
3617 }
3618 }
3619 Err(ErrorContext::new_missing(
3620 "ConntrackAttrs",
3621 "Timestamp",
3622 self.orig_loc,
3623 self.buf.as_ptr() as usize,
3624 ))
3625 }
3626 pub fn get_mark_mask(&self) -> Result<u32, ErrorContext> {
3627 let mut iter = self.clone();
3628 iter.pos = 0;
3629 for attr in iter {
3630 if let ConntrackAttrs::MarkMask(val) = attr? {
3631 return Ok(val);
3632 }
3633 }
3634 Err(ErrorContext::new_missing(
3635 "ConntrackAttrs",
3636 "MarkMask",
3637 self.orig_loc,
3638 self.buf.as_ptr() as usize,
3639 ))
3640 }
3641 pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
3642 let mut iter = self.clone();
3643 iter.pos = 0;
3644 for attr in iter {
3645 if let ConntrackAttrs::Labels(val) = attr? {
3646 return Ok(val);
3647 }
3648 }
3649 Err(ErrorContext::new_missing(
3650 "ConntrackAttrs",
3651 "Labels",
3652 self.orig_loc,
3653 self.buf.as_ptr() as usize,
3654 ))
3655 }
3656 pub fn get_labels_mask(&self) -> Result<&'a [u8], ErrorContext> {
3657 let mut iter = self.clone();
3658 iter.pos = 0;
3659 for attr in iter {
3660 if let ConntrackAttrs::LabelsMask(val) = attr? {
3661 return Ok(val);
3662 }
3663 }
3664 Err(ErrorContext::new_missing(
3665 "ConntrackAttrs",
3666 "LabelsMask",
3667 self.orig_loc,
3668 self.buf.as_ptr() as usize,
3669 ))
3670 }
3671 pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
3672 let mut iter = self.clone();
3673 iter.pos = 0;
3674 for attr in iter {
3675 if let ConntrackAttrs::Synproxy(val) = attr? {
3676 return Ok(val);
3677 }
3678 }
3679 Err(ErrorContext::new_missing(
3680 "ConntrackAttrs",
3681 "Synproxy",
3682 self.orig_loc,
3683 self.buf.as_ptr() as usize,
3684 ))
3685 }
3686 pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
3687 let mut iter = self.clone();
3688 iter.pos = 0;
3689 for attr in iter {
3690 if let ConntrackAttrs::Filter(val) = attr? {
3691 return Ok(val);
3692 }
3693 }
3694 Err(ErrorContext::new_missing(
3695 "ConntrackAttrs",
3696 "Filter",
3697 self.orig_loc,
3698 self.buf.as_ptr() as usize,
3699 ))
3700 }
3701 #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
3702 pub fn get_status_mask(&self) -> Result<u32, ErrorContext> {
3703 let mut iter = self.clone();
3704 iter.pos = 0;
3705 for attr in iter {
3706 if let ConntrackAttrs::StatusMask(val) = attr? {
3707 return Ok(val);
3708 }
3709 }
3710 Err(ErrorContext::new_missing(
3711 "ConntrackAttrs",
3712 "StatusMask",
3713 self.orig_loc,
3714 self.buf.as_ptr() as usize,
3715 ))
3716 }
3717 pub fn get_timestamp_event(&self) -> Result<u64, ErrorContext> {
3718 let mut iter = self.clone();
3719 iter.pos = 0;
3720 for attr in iter {
3721 if let ConntrackAttrs::TimestampEvent(val) = attr? {
3722 return Ok(val);
3723 }
3724 }
3725 Err(ErrorContext::new_missing(
3726 "ConntrackAttrs",
3727 "TimestampEvent",
3728 self.orig_loc,
3729 self.buf.as_ptr() as usize,
3730 ))
3731 }
3732}
3733impl ConntrackAttrs<'_> {
3734 pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackAttrs<'a> {
3735 IterableConntrackAttrs::with_loc(buf, buf.as_ptr() as usize)
3736 }
3737 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3738 let res = match r#type {
3739 1u16 => "TupleOrig",
3740 2u16 => "TupleReply",
3741 3u16 => "Status",
3742 4u16 => "Protoinfo",
3743 5u16 => "Help",
3744 6u16 => "NatSrc",
3745 7u16 => "Timeout",
3746 8u16 => "Mark",
3747 9u16 => "CountersOrig",
3748 10u16 => "CountersReply",
3749 11u16 => "Use",
3750 12u16 => "Id",
3751 13u16 => "NatDst",
3752 14u16 => "TupleMaster",
3753 15u16 => "SeqAdjOrig",
3754 16u16 => "SeqAdjReply",
3755 17u16 => "Secmark",
3756 18u16 => "Zone",
3757 19u16 => "Secctx",
3758 20u16 => "Timestamp",
3759 21u16 => "MarkMask",
3760 22u16 => "Labels",
3761 23u16 => "LabelsMask",
3762 24u16 => "Synproxy",
3763 25u16 => "Filter",
3764 26u16 => "StatusMask",
3765 27u16 => "TimestampEvent",
3766 _ => return None,
3767 };
3768 Some(res)
3769 }
3770}
3771#[derive(Clone, Copy, Default)]
3772pub struct IterableConntrackAttrs<'a> {
3773 buf: &'a [u8],
3774 pos: usize,
3775 orig_loc: usize,
3776}
3777impl<'a> IterableConntrackAttrs<'a> {
3778 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3779 Self {
3780 buf,
3781 pos: 0,
3782 orig_loc,
3783 }
3784 }
3785 pub fn get_buf(&self) -> &'a [u8] {
3786 self.buf
3787 }
3788}
3789impl<'a> Iterator for IterableConntrackAttrs<'a> {
3790 type Item = Result<ConntrackAttrs<'a>, ErrorContext>;
3791 fn next(&mut self) -> Option<Self::Item> {
3792 let pos = self.pos;
3793 let mut r#type;
3794 loop {
3795 r#type = None;
3796 if self.buf.len() == self.pos {
3797 return None;
3798 }
3799 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3800 break;
3801 };
3802 r#type = Some(header.r#type);
3803 let res = match header.r#type {
3804 1u16 => ConntrackAttrs::TupleOrig({
3805 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3806 let Some(val) = res else { break };
3807 val
3808 }),
3809 2u16 => ConntrackAttrs::TupleReply({
3810 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3811 let Some(val) = res else { break };
3812 val
3813 }),
3814 3u16 => ConntrackAttrs::Status({
3815 let res = parse_be_u32(next);
3816 let Some(val) = res else { break };
3817 val
3818 }),
3819 4u16 => ConntrackAttrs::Protoinfo({
3820 let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
3821 let Some(val) = res else { break };
3822 val
3823 }),
3824 5u16 => ConntrackAttrs::Help({
3825 let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
3826 let Some(val) = res else { break };
3827 val
3828 }),
3829 6u16 => ConntrackAttrs::NatSrc({
3830 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
3831 let Some(val) = res else { break };
3832 val
3833 }),
3834 7u16 => ConntrackAttrs::Timeout({
3835 let res = parse_be_u32(next);
3836 let Some(val) = res else { break };
3837 val
3838 }),
3839 8u16 => ConntrackAttrs::Mark({
3840 let res = parse_be_u32(next);
3841 let Some(val) = res else { break };
3842 val
3843 }),
3844 9u16 => ConntrackAttrs::CountersOrig({
3845 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
3846 let Some(val) = res else { break };
3847 val
3848 }),
3849 10u16 => ConntrackAttrs::CountersReply({
3850 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
3851 let Some(val) = res else { break };
3852 val
3853 }),
3854 11u16 => ConntrackAttrs::Use({
3855 let res = parse_be_u32(next);
3856 let Some(val) = res else { break };
3857 val
3858 }),
3859 12u16 => ConntrackAttrs::Id({
3860 let res = parse_be_u32(next);
3861 let Some(val) = res else { break };
3862 val
3863 }),
3864 13u16 => ConntrackAttrs::NatDst({
3865 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
3866 let Some(val) = res else { break };
3867 val
3868 }),
3869 14u16 => ConntrackAttrs::TupleMaster({
3870 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3871 let Some(val) = res else { break };
3872 val
3873 }),
3874 15u16 => ConntrackAttrs::SeqAdjOrig({
3875 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
3876 let Some(val) = res else { break };
3877 val
3878 }),
3879 16u16 => ConntrackAttrs::SeqAdjReply({
3880 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
3881 let Some(val) = res else { break };
3882 val
3883 }),
3884 17u16 => ConntrackAttrs::Secmark({
3885 let res = Some(next);
3886 let Some(val) = res else { break };
3887 val
3888 }),
3889 18u16 => ConntrackAttrs::Zone({
3890 let res = parse_be_u16(next);
3891 let Some(val) = res else { break };
3892 val
3893 }),
3894 19u16 => ConntrackAttrs::Secctx({
3895 let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
3896 let Some(val) = res else { break };
3897 val
3898 }),
3899 20u16 => ConntrackAttrs::Timestamp({
3900 let res = parse_be_u64(next);
3901 let Some(val) = res else { break };
3902 val
3903 }),
3904 21u16 => ConntrackAttrs::MarkMask({
3905 let res = parse_be_u32(next);
3906 let Some(val) = res else { break };
3907 val
3908 }),
3909 22u16 => ConntrackAttrs::Labels({
3910 let res = Some(next);
3911 let Some(val) = res else { break };
3912 val
3913 }),
3914 23u16 => ConntrackAttrs::LabelsMask({
3915 let res = Some(next);
3916 let Some(val) = res else { break };
3917 val
3918 }),
3919 24u16 => ConntrackAttrs::Synproxy({
3920 let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
3921 let Some(val) = res else { break };
3922 val
3923 }),
3924 25u16 => ConntrackAttrs::Filter({
3925 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
3926 let Some(val) = res else { break };
3927 val
3928 }),
3929 26u16 => ConntrackAttrs::StatusMask({
3930 let res = parse_be_u32(next);
3931 let Some(val) = res else { break };
3932 val
3933 }),
3934 27u16 => ConntrackAttrs::TimestampEvent({
3935 let res = parse_be_u64(next);
3936 let Some(val) = res else { break };
3937 val
3938 }),
3939 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3940 n => continue,
3941 };
3942 return Some(Ok(res));
3943 }
3944 Some(Err(ErrorContext::new(
3945 "ConntrackAttrs",
3946 r#type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
3947 self.orig_loc,
3948 self.buf.as_ptr().wrapping_add(pos) as usize,
3949 )))
3950 }
3951}
3952impl<'a> std::fmt::Debug for IterableConntrackAttrs<'_> {
3953 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3954 let mut fmt = f.debug_struct("ConntrackAttrs");
3955 for attr in self.clone() {
3956 let attr = match attr {
3957 Ok(a) => a,
3958 Err(err) => {
3959 fmt.finish()?;
3960 f.write_str("Err(")?;
3961 err.fmt(f)?;
3962 return f.write_str(")");
3963 }
3964 };
3965 match attr {
3966 ConntrackAttrs::TupleOrig(val) => fmt.field("TupleOrig", &val),
3967 ConntrackAttrs::TupleReply(val) => fmt.field("TupleReply", &val),
3968 ConntrackAttrs::Status(val) => {
3969 fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
3970 }
3971 ConntrackAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
3972 ConntrackAttrs::Help(val) => fmt.field("Help", &val),
3973 ConntrackAttrs::NatSrc(val) => fmt.field("NatSrc", &val),
3974 ConntrackAttrs::Timeout(val) => fmt.field("Timeout", &val),
3975 ConntrackAttrs::Mark(val) => fmt.field("Mark", &val),
3976 ConntrackAttrs::CountersOrig(val) => fmt.field("CountersOrig", &val),
3977 ConntrackAttrs::CountersReply(val) => fmt.field("CountersReply", &val),
3978 ConntrackAttrs::Use(val) => fmt.field("Use", &val),
3979 ConntrackAttrs::Id(val) => fmt.field("Id", &val),
3980 ConntrackAttrs::NatDst(val) => fmt.field("NatDst", &val),
3981 ConntrackAttrs::TupleMaster(val) => fmt.field("TupleMaster", &val),
3982 ConntrackAttrs::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
3983 ConntrackAttrs::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
3984 ConntrackAttrs::Secmark(val) => fmt.field("Secmark", &val),
3985 ConntrackAttrs::Zone(val) => fmt.field("Zone", &val),
3986 ConntrackAttrs::Secctx(val) => fmt.field("Secctx", &val),
3987 ConntrackAttrs::Timestamp(val) => fmt.field("Timestamp", &val),
3988 ConntrackAttrs::MarkMask(val) => fmt.field("MarkMask", &val),
3989 ConntrackAttrs::Labels(val) => fmt.field("Labels", &val),
3990 ConntrackAttrs::LabelsMask(val) => fmt.field("LabelsMask", &val),
3991 ConntrackAttrs::Synproxy(val) => fmt.field("Synproxy", &val),
3992 ConntrackAttrs::Filter(val) => fmt.field("Filter", &val),
3993 ConntrackAttrs::StatusMask(val) => fmt.field(
3994 "StatusMask",
3995 &FormatFlags(val.into(), NfCtStatus::from_value),
3996 ),
3997 ConntrackAttrs::TimestampEvent(val) => fmt.field("TimestampEvent", &val),
3998 };
3999 }
4000 fmt.finish()
4001 }
4002}
4003impl IterableConntrackAttrs<'_> {
4004 pub fn lookup_attr(
4005 &self,
4006 offset: usize,
4007 missing_type: Option<u16>,
4008 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4009 let mut stack = Vec::new();
4010 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4011 if cur == offset {
4012 stack.push(("ConntrackAttrs", offset));
4013 return (
4014 stack,
4015 missing_type.and_then(|t| ConntrackAttrs::attr_from_type(t)),
4016 );
4017 }
4018 if cur > offset || cur + self.buf.len() < offset {
4019 return (stack, None);
4020 }
4021 let mut attrs = self.clone();
4022 let mut last_off = cur + attrs.pos;
4023 let mut missing = None;
4024 while let Some(attr) = attrs.next() {
4025 let Ok(attr) = attr else { break };
4026 match attr {
4027 ConntrackAttrs::TupleOrig(val) => {
4028 (stack, missing) = val.lookup_attr(offset, missing_type);
4029 if !stack.is_empty() {
4030 break;
4031 }
4032 }
4033 ConntrackAttrs::TupleReply(val) => {
4034 (stack, missing) = val.lookup_attr(offset, missing_type);
4035 if !stack.is_empty() {
4036 break;
4037 }
4038 }
4039 ConntrackAttrs::Status(val) => {
4040 if last_off == offset {
4041 stack.push(("Status", last_off));
4042 break;
4043 }
4044 }
4045 ConntrackAttrs::Protoinfo(val) => {
4046 (stack, missing) = val.lookup_attr(offset, missing_type);
4047 if !stack.is_empty() {
4048 break;
4049 }
4050 }
4051 ConntrackAttrs::Help(val) => {
4052 (stack, missing) = val.lookup_attr(offset, missing_type);
4053 if !stack.is_empty() {
4054 break;
4055 }
4056 }
4057 ConntrackAttrs::NatSrc(val) => {
4058 (stack, missing) = val.lookup_attr(offset, missing_type);
4059 if !stack.is_empty() {
4060 break;
4061 }
4062 }
4063 ConntrackAttrs::Timeout(val) => {
4064 if last_off == offset {
4065 stack.push(("Timeout", last_off));
4066 break;
4067 }
4068 }
4069 ConntrackAttrs::Mark(val) => {
4070 if last_off == offset {
4071 stack.push(("Mark", last_off));
4072 break;
4073 }
4074 }
4075 ConntrackAttrs::CountersOrig(val) => {
4076 (stack, missing) = val.lookup_attr(offset, missing_type);
4077 if !stack.is_empty() {
4078 break;
4079 }
4080 }
4081 ConntrackAttrs::CountersReply(val) => {
4082 (stack, missing) = val.lookup_attr(offset, missing_type);
4083 if !stack.is_empty() {
4084 break;
4085 }
4086 }
4087 ConntrackAttrs::Use(val) => {
4088 if last_off == offset {
4089 stack.push(("Use", last_off));
4090 break;
4091 }
4092 }
4093 ConntrackAttrs::Id(val) => {
4094 if last_off == offset {
4095 stack.push(("Id", last_off));
4096 break;
4097 }
4098 }
4099 ConntrackAttrs::NatDst(val) => {
4100 (stack, missing) = val.lookup_attr(offset, missing_type);
4101 if !stack.is_empty() {
4102 break;
4103 }
4104 }
4105 ConntrackAttrs::TupleMaster(val) => {
4106 (stack, missing) = val.lookup_attr(offset, missing_type);
4107 if !stack.is_empty() {
4108 break;
4109 }
4110 }
4111 ConntrackAttrs::SeqAdjOrig(val) => {
4112 (stack, missing) = val.lookup_attr(offset, missing_type);
4113 if !stack.is_empty() {
4114 break;
4115 }
4116 }
4117 ConntrackAttrs::SeqAdjReply(val) => {
4118 (stack, missing) = val.lookup_attr(offset, missing_type);
4119 if !stack.is_empty() {
4120 break;
4121 }
4122 }
4123 ConntrackAttrs::Secmark(val) => {
4124 if last_off == offset {
4125 stack.push(("Secmark", last_off));
4126 break;
4127 }
4128 }
4129 ConntrackAttrs::Zone(val) => {
4130 if last_off == offset {
4131 stack.push(("Zone", last_off));
4132 break;
4133 }
4134 }
4135 ConntrackAttrs::Secctx(val) => {
4136 (stack, missing) = val.lookup_attr(offset, missing_type);
4137 if !stack.is_empty() {
4138 break;
4139 }
4140 }
4141 ConntrackAttrs::Timestamp(val) => {
4142 if last_off == offset {
4143 stack.push(("Timestamp", last_off));
4144 break;
4145 }
4146 }
4147 ConntrackAttrs::MarkMask(val) => {
4148 if last_off == offset {
4149 stack.push(("MarkMask", last_off));
4150 break;
4151 }
4152 }
4153 ConntrackAttrs::Labels(val) => {
4154 if last_off == offset {
4155 stack.push(("Labels", last_off));
4156 break;
4157 }
4158 }
4159 ConntrackAttrs::LabelsMask(val) => {
4160 if last_off == offset {
4161 stack.push(("LabelsMask", last_off));
4162 break;
4163 }
4164 }
4165 ConntrackAttrs::Synproxy(val) => {
4166 (stack, missing) = val.lookup_attr(offset, missing_type);
4167 if !stack.is_empty() {
4168 break;
4169 }
4170 }
4171 ConntrackAttrs::Filter(val) => {
4172 (stack, missing) = val.lookup_attr(offset, missing_type);
4173 if !stack.is_empty() {
4174 break;
4175 }
4176 }
4177 ConntrackAttrs::StatusMask(val) => {
4178 if last_off == offset {
4179 stack.push(("StatusMask", last_off));
4180 break;
4181 }
4182 }
4183 ConntrackAttrs::TimestampEvent(val) => {
4184 if last_off == offset {
4185 stack.push(("TimestampEvent", last_off));
4186 break;
4187 }
4188 }
4189 _ => {}
4190 };
4191 last_off = cur + attrs.pos;
4192 }
4193 if !stack.is_empty() {
4194 stack.push(("ConntrackAttrs", cur));
4195 }
4196 (stack, missing)
4197 }
4198}
4199#[derive(Clone)]
4200pub enum ConntrackStatsAttrs {
4201 #[doc = "obsolete"]
4202 Searched(u32),
4203 Found(u32),
4204 #[doc = "obsolete"]
4205 New(u32),
4206 #[doc = "obsolete"]
4207 Invalid(u32),
4208 #[doc = "obsolete"]
4209 Ignore(u32),
4210 #[doc = "obsolete"]
4211 Delete(u32),
4212 #[doc = "obsolete"]
4213 DeleteList(u32),
4214 Insert(u32),
4215 InsertFailed(u32),
4216 Drop(u32),
4217 EarlyDrop(u32),
4218 Error(u32),
4219 SearchRestart(u32),
4220 ClashResolve(u32),
4221 ChainToolong(u32),
4222}
4223impl<'a> IterableConntrackStatsAttrs<'a> {
4224 #[doc = "obsolete"]
4225 pub fn get_searched(&self) -> Result<u32, ErrorContext> {
4226 let mut iter = self.clone();
4227 iter.pos = 0;
4228 for attr in iter {
4229 if let ConntrackStatsAttrs::Searched(val) = attr? {
4230 return Ok(val);
4231 }
4232 }
4233 Err(ErrorContext::new_missing(
4234 "ConntrackStatsAttrs",
4235 "Searched",
4236 self.orig_loc,
4237 self.buf.as_ptr() as usize,
4238 ))
4239 }
4240 pub fn get_found(&self) -> Result<u32, ErrorContext> {
4241 let mut iter = self.clone();
4242 iter.pos = 0;
4243 for attr in iter {
4244 if let ConntrackStatsAttrs::Found(val) = attr? {
4245 return Ok(val);
4246 }
4247 }
4248 Err(ErrorContext::new_missing(
4249 "ConntrackStatsAttrs",
4250 "Found",
4251 self.orig_loc,
4252 self.buf.as_ptr() as usize,
4253 ))
4254 }
4255 #[doc = "obsolete"]
4256 pub fn get_new(&self) -> Result<u32, ErrorContext> {
4257 let mut iter = self.clone();
4258 iter.pos = 0;
4259 for attr in iter {
4260 if let ConntrackStatsAttrs::New(val) = attr? {
4261 return Ok(val);
4262 }
4263 }
4264 Err(ErrorContext::new_missing(
4265 "ConntrackStatsAttrs",
4266 "New",
4267 self.orig_loc,
4268 self.buf.as_ptr() as usize,
4269 ))
4270 }
4271 #[doc = "obsolete"]
4272 pub fn get_invalid(&self) -> Result<u32, ErrorContext> {
4273 let mut iter = self.clone();
4274 iter.pos = 0;
4275 for attr in iter {
4276 if let ConntrackStatsAttrs::Invalid(val) = attr? {
4277 return Ok(val);
4278 }
4279 }
4280 Err(ErrorContext::new_missing(
4281 "ConntrackStatsAttrs",
4282 "Invalid",
4283 self.orig_loc,
4284 self.buf.as_ptr() as usize,
4285 ))
4286 }
4287 #[doc = "obsolete"]
4288 pub fn get_ignore(&self) -> Result<u32, ErrorContext> {
4289 let mut iter = self.clone();
4290 iter.pos = 0;
4291 for attr in iter {
4292 if let ConntrackStatsAttrs::Ignore(val) = attr? {
4293 return Ok(val);
4294 }
4295 }
4296 Err(ErrorContext::new_missing(
4297 "ConntrackStatsAttrs",
4298 "Ignore",
4299 self.orig_loc,
4300 self.buf.as_ptr() as usize,
4301 ))
4302 }
4303 #[doc = "obsolete"]
4304 pub fn get_delete(&self) -> Result<u32, ErrorContext> {
4305 let mut iter = self.clone();
4306 iter.pos = 0;
4307 for attr in iter {
4308 if let ConntrackStatsAttrs::Delete(val) = attr? {
4309 return Ok(val);
4310 }
4311 }
4312 Err(ErrorContext::new_missing(
4313 "ConntrackStatsAttrs",
4314 "Delete",
4315 self.orig_loc,
4316 self.buf.as_ptr() as usize,
4317 ))
4318 }
4319 #[doc = "obsolete"]
4320 pub fn get_delete_list(&self) -> Result<u32, ErrorContext> {
4321 let mut iter = self.clone();
4322 iter.pos = 0;
4323 for attr in iter {
4324 if let ConntrackStatsAttrs::DeleteList(val) = attr? {
4325 return Ok(val);
4326 }
4327 }
4328 Err(ErrorContext::new_missing(
4329 "ConntrackStatsAttrs",
4330 "DeleteList",
4331 self.orig_loc,
4332 self.buf.as_ptr() as usize,
4333 ))
4334 }
4335 pub fn get_insert(&self) -> Result<u32, ErrorContext> {
4336 let mut iter = self.clone();
4337 iter.pos = 0;
4338 for attr in iter {
4339 if let ConntrackStatsAttrs::Insert(val) = attr? {
4340 return Ok(val);
4341 }
4342 }
4343 Err(ErrorContext::new_missing(
4344 "ConntrackStatsAttrs",
4345 "Insert",
4346 self.orig_loc,
4347 self.buf.as_ptr() as usize,
4348 ))
4349 }
4350 pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
4351 let mut iter = self.clone();
4352 iter.pos = 0;
4353 for attr in iter {
4354 if let ConntrackStatsAttrs::InsertFailed(val) = attr? {
4355 return Ok(val);
4356 }
4357 }
4358 Err(ErrorContext::new_missing(
4359 "ConntrackStatsAttrs",
4360 "InsertFailed",
4361 self.orig_loc,
4362 self.buf.as_ptr() as usize,
4363 ))
4364 }
4365 pub fn get_drop(&self) -> Result<u32, ErrorContext> {
4366 let mut iter = self.clone();
4367 iter.pos = 0;
4368 for attr in iter {
4369 if let ConntrackStatsAttrs::Drop(val) = attr? {
4370 return Ok(val);
4371 }
4372 }
4373 Err(ErrorContext::new_missing(
4374 "ConntrackStatsAttrs",
4375 "Drop",
4376 self.orig_loc,
4377 self.buf.as_ptr() as usize,
4378 ))
4379 }
4380 pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
4381 let mut iter = self.clone();
4382 iter.pos = 0;
4383 for attr in iter {
4384 if let ConntrackStatsAttrs::EarlyDrop(val) = attr? {
4385 return Ok(val);
4386 }
4387 }
4388 Err(ErrorContext::new_missing(
4389 "ConntrackStatsAttrs",
4390 "EarlyDrop",
4391 self.orig_loc,
4392 self.buf.as_ptr() as usize,
4393 ))
4394 }
4395 pub fn get_error(&self) -> Result<u32, ErrorContext> {
4396 let mut iter = self.clone();
4397 iter.pos = 0;
4398 for attr in iter {
4399 if let ConntrackStatsAttrs::Error(val) = attr? {
4400 return Ok(val);
4401 }
4402 }
4403 Err(ErrorContext::new_missing(
4404 "ConntrackStatsAttrs",
4405 "Error",
4406 self.orig_loc,
4407 self.buf.as_ptr() as usize,
4408 ))
4409 }
4410 pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
4411 let mut iter = self.clone();
4412 iter.pos = 0;
4413 for attr in iter {
4414 if let ConntrackStatsAttrs::SearchRestart(val) = attr? {
4415 return Ok(val);
4416 }
4417 }
4418 Err(ErrorContext::new_missing(
4419 "ConntrackStatsAttrs",
4420 "SearchRestart",
4421 self.orig_loc,
4422 self.buf.as_ptr() as usize,
4423 ))
4424 }
4425 pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
4426 let mut iter = self.clone();
4427 iter.pos = 0;
4428 for attr in iter {
4429 if let ConntrackStatsAttrs::ClashResolve(val) = attr? {
4430 return Ok(val);
4431 }
4432 }
4433 Err(ErrorContext::new_missing(
4434 "ConntrackStatsAttrs",
4435 "ClashResolve",
4436 self.orig_loc,
4437 self.buf.as_ptr() as usize,
4438 ))
4439 }
4440 pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
4441 let mut iter = self.clone();
4442 iter.pos = 0;
4443 for attr in iter {
4444 if let ConntrackStatsAttrs::ChainToolong(val) = attr? {
4445 return Ok(val);
4446 }
4447 }
4448 Err(ErrorContext::new_missing(
4449 "ConntrackStatsAttrs",
4450 "ChainToolong",
4451 self.orig_loc,
4452 self.buf.as_ptr() as usize,
4453 ))
4454 }
4455}
4456impl ConntrackStatsAttrs {
4457 pub fn new<'a>(buf: &'a [u8]) -> IterableConntrackStatsAttrs<'a> {
4458 IterableConntrackStatsAttrs::with_loc(buf, buf.as_ptr() as usize)
4459 }
4460 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4461 let res = match r#type {
4462 1u16 => "Searched",
4463 2u16 => "Found",
4464 3u16 => "New",
4465 4u16 => "Invalid",
4466 5u16 => "Ignore",
4467 6u16 => "Delete",
4468 7u16 => "DeleteList",
4469 8u16 => "Insert",
4470 9u16 => "InsertFailed",
4471 10u16 => "Drop",
4472 11u16 => "EarlyDrop",
4473 12u16 => "Error",
4474 13u16 => "SearchRestart",
4475 14u16 => "ClashResolve",
4476 15u16 => "ChainToolong",
4477 _ => return None,
4478 };
4479 Some(res)
4480 }
4481}
4482#[derive(Clone, Copy, Default)]
4483pub struct IterableConntrackStatsAttrs<'a> {
4484 buf: &'a [u8],
4485 pos: usize,
4486 orig_loc: usize,
4487}
4488impl<'a> IterableConntrackStatsAttrs<'a> {
4489 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4490 Self {
4491 buf,
4492 pos: 0,
4493 orig_loc,
4494 }
4495 }
4496 pub fn get_buf(&self) -> &'a [u8] {
4497 self.buf
4498 }
4499}
4500impl<'a> Iterator for IterableConntrackStatsAttrs<'a> {
4501 type Item = Result<ConntrackStatsAttrs, ErrorContext>;
4502 fn next(&mut self) -> Option<Self::Item> {
4503 let pos = self.pos;
4504 let mut r#type;
4505 loop {
4506 r#type = None;
4507 if self.buf.len() == self.pos {
4508 return None;
4509 }
4510 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4511 break;
4512 };
4513 r#type = Some(header.r#type);
4514 let res = match header.r#type {
4515 1u16 => ConntrackStatsAttrs::Searched({
4516 let res = parse_be_u32(next);
4517 let Some(val) = res else { break };
4518 val
4519 }),
4520 2u16 => ConntrackStatsAttrs::Found({
4521 let res = parse_be_u32(next);
4522 let Some(val) = res else { break };
4523 val
4524 }),
4525 3u16 => ConntrackStatsAttrs::New({
4526 let res = parse_be_u32(next);
4527 let Some(val) = res else { break };
4528 val
4529 }),
4530 4u16 => ConntrackStatsAttrs::Invalid({
4531 let res = parse_be_u32(next);
4532 let Some(val) = res else { break };
4533 val
4534 }),
4535 5u16 => ConntrackStatsAttrs::Ignore({
4536 let res = parse_be_u32(next);
4537 let Some(val) = res else { break };
4538 val
4539 }),
4540 6u16 => ConntrackStatsAttrs::Delete({
4541 let res = parse_be_u32(next);
4542 let Some(val) = res else { break };
4543 val
4544 }),
4545 7u16 => ConntrackStatsAttrs::DeleteList({
4546 let res = parse_be_u32(next);
4547 let Some(val) = res else { break };
4548 val
4549 }),
4550 8u16 => ConntrackStatsAttrs::Insert({
4551 let res = parse_be_u32(next);
4552 let Some(val) = res else { break };
4553 val
4554 }),
4555 9u16 => ConntrackStatsAttrs::InsertFailed({
4556 let res = parse_be_u32(next);
4557 let Some(val) = res else { break };
4558 val
4559 }),
4560 10u16 => ConntrackStatsAttrs::Drop({
4561 let res = parse_be_u32(next);
4562 let Some(val) = res else { break };
4563 val
4564 }),
4565 11u16 => ConntrackStatsAttrs::EarlyDrop({
4566 let res = parse_be_u32(next);
4567 let Some(val) = res else { break };
4568 val
4569 }),
4570 12u16 => ConntrackStatsAttrs::Error({
4571 let res = parse_be_u32(next);
4572 let Some(val) = res else { break };
4573 val
4574 }),
4575 13u16 => ConntrackStatsAttrs::SearchRestart({
4576 let res = parse_be_u32(next);
4577 let Some(val) = res else { break };
4578 val
4579 }),
4580 14u16 => ConntrackStatsAttrs::ClashResolve({
4581 let res = parse_be_u32(next);
4582 let Some(val) = res else { break };
4583 val
4584 }),
4585 15u16 => ConntrackStatsAttrs::ChainToolong({
4586 let res = parse_be_u32(next);
4587 let Some(val) = res else { break };
4588 val
4589 }),
4590 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4591 n => continue,
4592 };
4593 return Some(Ok(res));
4594 }
4595 Some(Err(ErrorContext::new(
4596 "ConntrackStatsAttrs",
4597 r#type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4598 self.orig_loc,
4599 self.buf.as_ptr().wrapping_add(pos) as usize,
4600 )))
4601 }
4602}
4603impl std::fmt::Debug for IterableConntrackStatsAttrs<'_> {
4604 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4605 let mut fmt = f.debug_struct("ConntrackStatsAttrs");
4606 for attr in self.clone() {
4607 let attr = match attr {
4608 Ok(a) => a,
4609 Err(err) => {
4610 fmt.finish()?;
4611 f.write_str("Err(")?;
4612 err.fmt(f)?;
4613 return f.write_str(")");
4614 }
4615 };
4616 match attr {
4617 ConntrackStatsAttrs::Searched(val) => fmt.field("Searched", &val),
4618 ConntrackStatsAttrs::Found(val) => fmt.field("Found", &val),
4619 ConntrackStatsAttrs::New(val) => fmt.field("New", &val),
4620 ConntrackStatsAttrs::Invalid(val) => fmt.field("Invalid", &val),
4621 ConntrackStatsAttrs::Ignore(val) => fmt.field("Ignore", &val),
4622 ConntrackStatsAttrs::Delete(val) => fmt.field("Delete", &val),
4623 ConntrackStatsAttrs::DeleteList(val) => fmt.field("DeleteList", &val),
4624 ConntrackStatsAttrs::Insert(val) => fmt.field("Insert", &val),
4625 ConntrackStatsAttrs::InsertFailed(val) => fmt.field("InsertFailed", &val),
4626 ConntrackStatsAttrs::Drop(val) => fmt.field("Drop", &val),
4627 ConntrackStatsAttrs::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
4628 ConntrackStatsAttrs::Error(val) => fmt.field("Error", &val),
4629 ConntrackStatsAttrs::SearchRestart(val) => fmt.field("SearchRestart", &val),
4630 ConntrackStatsAttrs::ClashResolve(val) => fmt.field("ClashResolve", &val),
4631 ConntrackStatsAttrs::ChainToolong(val) => fmt.field("ChainToolong", &val),
4632 };
4633 }
4634 fmt.finish()
4635 }
4636}
4637impl IterableConntrackStatsAttrs<'_> {
4638 pub fn lookup_attr(
4639 &self,
4640 offset: usize,
4641 missing_type: Option<u16>,
4642 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4643 let mut stack = Vec::new();
4644 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4645 if cur == offset {
4646 stack.push(("ConntrackStatsAttrs", offset));
4647 return (
4648 stack,
4649 missing_type.and_then(|t| ConntrackStatsAttrs::attr_from_type(t)),
4650 );
4651 }
4652 if cur > offset || cur + self.buf.len() < offset {
4653 return (stack, None);
4654 }
4655 let mut attrs = self.clone();
4656 let mut last_off = cur + attrs.pos;
4657 while let Some(attr) = attrs.next() {
4658 let Ok(attr) = attr else { break };
4659 match attr {
4660 ConntrackStatsAttrs::Searched(val) => {
4661 if last_off == offset {
4662 stack.push(("Searched", last_off));
4663 break;
4664 }
4665 }
4666 ConntrackStatsAttrs::Found(val) => {
4667 if last_off == offset {
4668 stack.push(("Found", last_off));
4669 break;
4670 }
4671 }
4672 ConntrackStatsAttrs::New(val) => {
4673 if last_off == offset {
4674 stack.push(("New", last_off));
4675 break;
4676 }
4677 }
4678 ConntrackStatsAttrs::Invalid(val) => {
4679 if last_off == offset {
4680 stack.push(("Invalid", last_off));
4681 break;
4682 }
4683 }
4684 ConntrackStatsAttrs::Ignore(val) => {
4685 if last_off == offset {
4686 stack.push(("Ignore", last_off));
4687 break;
4688 }
4689 }
4690 ConntrackStatsAttrs::Delete(val) => {
4691 if last_off == offset {
4692 stack.push(("Delete", last_off));
4693 break;
4694 }
4695 }
4696 ConntrackStatsAttrs::DeleteList(val) => {
4697 if last_off == offset {
4698 stack.push(("DeleteList", last_off));
4699 break;
4700 }
4701 }
4702 ConntrackStatsAttrs::Insert(val) => {
4703 if last_off == offset {
4704 stack.push(("Insert", last_off));
4705 break;
4706 }
4707 }
4708 ConntrackStatsAttrs::InsertFailed(val) => {
4709 if last_off == offset {
4710 stack.push(("InsertFailed", last_off));
4711 break;
4712 }
4713 }
4714 ConntrackStatsAttrs::Drop(val) => {
4715 if last_off == offset {
4716 stack.push(("Drop", last_off));
4717 break;
4718 }
4719 }
4720 ConntrackStatsAttrs::EarlyDrop(val) => {
4721 if last_off == offset {
4722 stack.push(("EarlyDrop", last_off));
4723 break;
4724 }
4725 }
4726 ConntrackStatsAttrs::Error(val) => {
4727 if last_off == offset {
4728 stack.push(("Error", last_off));
4729 break;
4730 }
4731 }
4732 ConntrackStatsAttrs::SearchRestart(val) => {
4733 if last_off == offset {
4734 stack.push(("SearchRestart", last_off));
4735 break;
4736 }
4737 }
4738 ConntrackStatsAttrs::ClashResolve(val) => {
4739 if last_off == offset {
4740 stack.push(("ClashResolve", last_off));
4741 break;
4742 }
4743 }
4744 ConntrackStatsAttrs::ChainToolong(val) => {
4745 if last_off == offset {
4746 stack.push(("ChainToolong", last_off));
4747 break;
4748 }
4749 }
4750 _ => {}
4751 };
4752 last_off = cur + attrs.pos;
4753 }
4754 if !stack.is_empty() {
4755 stack.push(("ConntrackStatsAttrs", cur));
4756 }
4757 (stack, None)
4758 }
4759}
4760pub struct PushCounterAttrs<Prev: Rec> {
4761 pub(crate) prev: Option<Prev>,
4762 pub(crate) header_offset: Option<usize>,
4763}
4764impl<Prev: Rec> Rec for PushCounterAttrs<Prev> {
4765 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4766 self.prev.as_mut().unwrap().as_rec_mut()
4767 }
4768 fn as_rec(&self) -> &Vec<u8> {
4769 self.prev.as_ref().unwrap().as_rec()
4770 }
4771}
4772impl<Prev: Rec> PushCounterAttrs<Prev> {
4773 pub fn new(prev: Prev) -> Self {
4774 Self {
4775 prev: Some(prev),
4776 header_offset: None,
4777 }
4778 }
4779 pub fn end_nested(mut self) -> Prev {
4780 let mut prev = self.prev.take().unwrap();
4781 if let Some(header_offset) = &self.header_offset {
4782 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4783 }
4784 prev
4785 }
4786 pub fn push_packets(mut self, value: u64) -> Self {
4787 push_header(self.as_rec_mut(), 1u16, 8 as u16);
4788 self.as_rec_mut().extend(value.to_be_bytes());
4789 self
4790 }
4791 pub fn push_bytes(mut self, value: u64) -> Self {
4792 push_header(self.as_rec_mut(), 2u16, 8 as u16);
4793 self.as_rec_mut().extend(value.to_be_bytes());
4794 self
4795 }
4796 pub fn push_packets_old(mut self, value: u32) -> Self {
4797 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4798 self.as_rec_mut().extend(value.to_ne_bytes());
4799 self
4800 }
4801 pub fn push_bytes_old(mut self, value: u32) -> Self {
4802 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4803 self.as_rec_mut().extend(value.to_ne_bytes());
4804 self
4805 }
4806 pub fn push_pad(mut self, value: &[u8]) -> Self {
4807 push_header(self.as_rec_mut(), 5u16, value.len() as u16);
4808 self.as_rec_mut().extend(value);
4809 self
4810 }
4811}
4812impl<Prev: Rec> Drop for PushCounterAttrs<Prev> {
4813 fn drop(&mut self) {
4814 if let Some(prev) = &mut self.prev {
4815 if let Some(header_offset) = &self.header_offset {
4816 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4817 }
4818 }
4819 }
4820}
4821pub struct PushTupleProtoAttrs<Prev: Rec> {
4822 pub(crate) prev: Option<Prev>,
4823 pub(crate) header_offset: Option<usize>,
4824}
4825impl<Prev: Rec> Rec for PushTupleProtoAttrs<Prev> {
4826 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4827 self.prev.as_mut().unwrap().as_rec_mut()
4828 }
4829 fn as_rec(&self) -> &Vec<u8> {
4830 self.prev.as_ref().unwrap().as_rec()
4831 }
4832}
4833impl<Prev: Rec> PushTupleProtoAttrs<Prev> {
4834 pub fn new(prev: Prev) -> Self {
4835 Self {
4836 prev: Some(prev),
4837 header_offset: None,
4838 }
4839 }
4840 pub fn end_nested(mut self) -> Prev {
4841 let mut prev = self.prev.take().unwrap();
4842 if let Some(header_offset) = &self.header_offset {
4843 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4844 }
4845 prev
4846 }
4847 #[doc = "l4 protocol number"]
4848 pub fn push_proto_num(mut self, value: u8) -> Self {
4849 push_header(self.as_rec_mut(), 1u16, 1 as u16);
4850 self.as_rec_mut().extend(value.to_ne_bytes());
4851 self
4852 }
4853 #[doc = "l4 source port"]
4854 pub fn push_proto_src_port(mut self, value: u16) -> Self {
4855 push_header(self.as_rec_mut(), 2u16, 2 as u16);
4856 self.as_rec_mut().extend(value.to_be_bytes());
4857 self
4858 }
4859 #[doc = "l4 source port"]
4860 pub fn push_proto_dst_port(mut self, value: u16) -> Self {
4861 push_header(self.as_rec_mut(), 3u16, 2 as u16);
4862 self.as_rec_mut().extend(value.to_be_bytes());
4863 self
4864 }
4865 #[doc = "l4 icmp id"]
4866 pub fn push_proto_icmp_id(mut self, value: u16) -> Self {
4867 push_header(self.as_rec_mut(), 4u16, 2 as u16);
4868 self.as_rec_mut().extend(value.to_be_bytes());
4869 self
4870 }
4871 pub fn push_proto_icmp_type(mut self, value: u8) -> Self {
4872 push_header(self.as_rec_mut(), 5u16, 1 as u16);
4873 self.as_rec_mut().extend(value.to_ne_bytes());
4874 self
4875 }
4876 pub fn push_proto_icmp_code(mut self, value: u8) -> Self {
4877 push_header(self.as_rec_mut(), 6u16, 1 as u16);
4878 self.as_rec_mut().extend(value.to_ne_bytes());
4879 self
4880 }
4881 #[doc = "l4 icmp id"]
4882 pub fn push_proto_icmpv6_id(mut self, value: u16) -> Self {
4883 push_header(self.as_rec_mut(), 7u16, 2 as u16);
4884 self.as_rec_mut().extend(value.to_be_bytes());
4885 self
4886 }
4887 pub fn push_proto_icmpv6_type(mut self, value: u8) -> Self {
4888 push_header(self.as_rec_mut(), 8u16, 1 as u16);
4889 self.as_rec_mut().extend(value.to_ne_bytes());
4890 self
4891 }
4892 pub fn push_proto_icmpv6_code(mut self, value: u8) -> Self {
4893 push_header(self.as_rec_mut(), 9u16, 1 as u16);
4894 self.as_rec_mut().extend(value.to_ne_bytes());
4895 self
4896 }
4897}
4898impl<Prev: Rec> Drop for PushTupleProtoAttrs<Prev> {
4899 fn drop(&mut self) {
4900 if let Some(prev) = &mut self.prev {
4901 if let Some(header_offset) = &self.header_offset {
4902 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4903 }
4904 }
4905 }
4906}
4907pub struct PushTupleIpAttrs<Prev: Rec> {
4908 pub(crate) prev: Option<Prev>,
4909 pub(crate) header_offset: Option<usize>,
4910}
4911impl<Prev: Rec> Rec for PushTupleIpAttrs<Prev> {
4912 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4913 self.prev.as_mut().unwrap().as_rec_mut()
4914 }
4915 fn as_rec(&self) -> &Vec<u8> {
4916 self.prev.as_ref().unwrap().as_rec()
4917 }
4918}
4919impl<Prev: Rec> PushTupleIpAttrs<Prev> {
4920 pub fn new(prev: Prev) -> Self {
4921 Self {
4922 prev: Some(prev),
4923 header_offset: None,
4924 }
4925 }
4926 pub fn end_nested(mut self) -> Prev {
4927 let mut prev = self.prev.take().unwrap();
4928 if let Some(header_offset) = &self.header_offset {
4929 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4930 }
4931 prev
4932 }
4933 #[doc = "ipv4 source address"]
4934 pub fn push_ip_v4_src(mut self, value: std::net::Ipv4Addr) -> Self {
4935 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4936 self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4937 self
4938 }
4939 #[doc = "ipv4 destination address"]
4940 pub fn push_ip_v4_dst(mut self, value: std::net::Ipv4Addr) -> Self {
4941 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4942 self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4943 self
4944 }
4945 #[doc = "ipv6 source address"]
4946 pub fn push_ip_v6_src(mut self, value: std::net::Ipv6Addr) -> Self {
4947 push_header(self.as_rec_mut(), 3u16, 16 as u16);
4948 self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4949 self
4950 }
4951 #[doc = "ipv6 destination address"]
4952 pub fn push_ip_v6_dst(mut self, value: std::net::Ipv6Addr) -> Self {
4953 push_header(self.as_rec_mut(), 4u16, 16 as u16);
4954 self.as_rec_mut().extend(&value.to_bits().to_be_bytes());
4955 self
4956 }
4957}
4958impl<Prev: Rec> Drop for PushTupleIpAttrs<Prev> {
4959 fn drop(&mut self) {
4960 if let Some(prev) = &mut self.prev {
4961 if let Some(header_offset) = &self.header_offset {
4962 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4963 }
4964 }
4965 }
4966}
4967pub struct PushTupleAttrs<Prev: Rec> {
4968 pub(crate) prev: Option<Prev>,
4969 pub(crate) header_offset: Option<usize>,
4970}
4971impl<Prev: Rec> Rec for PushTupleAttrs<Prev> {
4972 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4973 self.prev.as_mut().unwrap().as_rec_mut()
4974 }
4975 fn as_rec(&self) -> &Vec<u8> {
4976 self.prev.as_ref().unwrap().as_rec()
4977 }
4978}
4979impl<Prev: Rec> PushTupleAttrs<Prev> {
4980 pub fn new(prev: Prev) -> Self {
4981 Self {
4982 prev: Some(prev),
4983 header_offset: None,
4984 }
4985 }
4986 pub fn end_nested(mut self) -> Prev {
4987 let mut prev = self.prev.take().unwrap();
4988 if let Some(header_offset) = &self.header_offset {
4989 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4990 }
4991 prev
4992 }
4993 #[doc = "conntrack l3 information"]
4994 pub fn nested_tuple_ip(mut self) -> PushTupleIpAttrs<Self> {
4995 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4996 PushTupleIpAttrs {
4997 prev: Some(self),
4998 header_offset: Some(header_offset),
4999 }
5000 }
5001 #[doc = "conntrack l4 information"]
5002 pub fn nested_tuple_proto(mut self) -> PushTupleProtoAttrs<Self> {
5003 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5004 PushTupleProtoAttrs {
5005 prev: Some(self),
5006 header_offset: Some(header_offset),
5007 }
5008 }
5009 #[doc = "conntrack zone id"]
5010 pub fn push_tuple_zone(mut self, value: u16) -> Self {
5011 push_header(self.as_rec_mut(), 3u16, 2 as u16);
5012 self.as_rec_mut().extend(value.to_be_bytes());
5013 self
5014 }
5015}
5016impl<Prev: Rec> Drop for PushTupleAttrs<Prev> {
5017 fn drop(&mut self) {
5018 if let Some(prev) = &mut self.prev {
5019 if let Some(header_offset) = &self.header_offset {
5020 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5021 }
5022 }
5023 }
5024}
5025pub struct PushProtoinfoTcpAttrs<Prev: Rec> {
5026 pub(crate) prev: Option<Prev>,
5027 pub(crate) header_offset: Option<usize>,
5028}
5029impl<Prev: Rec> Rec for PushProtoinfoTcpAttrs<Prev> {
5030 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5031 self.prev.as_mut().unwrap().as_rec_mut()
5032 }
5033 fn as_rec(&self) -> &Vec<u8> {
5034 self.prev.as_ref().unwrap().as_rec()
5035 }
5036}
5037impl<Prev: Rec> PushProtoinfoTcpAttrs<Prev> {
5038 pub fn new(prev: Prev) -> Self {
5039 Self {
5040 prev: Some(prev),
5041 header_offset: None,
5042 }
5043 }
5044 pub fn end_nested(mut self) -> Prev {
5045 let mut prev = self.prev.take().unwrap();
5046 if let Some(header_offset) = &self.header_offset {
5047 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5048 }
5049 prev
5050 }
5051 #[doc = "tcp connection state\nAssociated type: \"NfCtTcpState\" (enum)"]
5052 pub fn push_tcp_state(mut self, value: u8) -> Self {
5053 push_header(self.as_rec_mut(), 1u16, 1 as u16);
5054 self.as_rec_mut().extend(value.to_ne_bytes());
5055 self
5056 }
5057 #[doc = "window scaling factor in original direction"]
5058 pub fn push_tcp_wscale_original(mut self, value: u8) -> Self {
5059 push_header(self.as_rec_mut(), 2u16, 1 as u16);
5060 self.as_rec_mut().extend(value.to_ne_bytes());
5061 self
5062 }
5063 #[doc = "window scaling factor in reply direction"]
5064 pub fn push_tcp_wscale_reply(mut self, value: u8) -> Self {
5065 push_header(self.as_rec_mut(), 3u16, 1 as u16);
5066 self.as_rec_mut().extend(value.to_ne_bytes());
5067 self
5068 }
5069 pub fn push_tcp_flags_original(mut self, value: PushNfCtTcpFlagsMask) -> Self {
5070 push_header(self.as_rec_mut(), 4u16, value.as_slice().len() as u16);
5071 self.as_rec_mut().extend(value.as_slice());
5072 self
5073 }
5074 pub fn push_tcp_flags_reply(mut self, value: PushNfCtTcpFlagsMask) -> Self {
5075 push_header(self.as_rec_mut(), 5u16, value.as_slice().len() as u16);
5076 self.as_rec_mut().extend(value.as_slice());
5077 self
5078 }
5079}
5080impl<Prev: Rec> Drop for PushProtoinfoTcpAttrs<Prev> {
5081 fn drop(&mut self) {
5082 if let Some(prev) = &mut self.prev {
5083 if let Some(header_offset) = &self.header_offset {
5084 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5085 }
5086 }
5087 }
5088}
5089pub struct PushProtoinfoDccpAttrs<Prev: Rec> {
5090 pub(crate) prev: Option<Prev>,
5091 pub(crate) header_offset: Option<usize>,
5092}
5093impl<Prev: Rec> Rec for PushProtoinfoDccpAttrs<Prev> {
5094 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5095 self.prev.as_mut().unwrap().as_rec_mut()
5096 }
5097 fn as_rec(&self) -> &Vec<u8> {
5098 self.prev.as_ref().unwrap().as_rec()
5099 }
5100}
5101impl<Prev: Rec> PushProtoinfoDccpAttrs<Prev> {
5102 pub fn new(prev: Prev) -> Self {
5103 Self {
5104 prev: Some(prev),
5105 header_offset: None,
5106 }
5107 }
5108 pub fn end_nested(mut self) -> Prev {
5109 let mut prev = self.prev.take().unwrap();
5110 if let Some(header_offset) = &self.header_offset {
5111 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5112 }
5113 prev
5114 }
5115 #[doc = "dccp connection state"]
5116 pub fn push_dccp_state(mut self, value: u8) -> Self {
5117 push_header(self.as_rec_mut(), 1u16, 1 as u16);
5118 self.as_rec_mut().extend(value.to_ne_bytes());
5119 self
5120 }
5121 pub fn push_dccp_role(mut self, value: u8) -> Self {
5122 push_header(self.as_rec_mut(), 2u16, 1 as u16);
5123 self.as_rec_mut().extend(value.to_ne_bytes());
5124 self
5125 }
5126 pub fn push_dccp_handshake_seq(mut self, value: u64) -> Self {
5127 push_header(self.as_rec_mut(), 3u16, 8 as u16);
5128 self.as_rec_mut().extend(value.to_be_bytes());
5129 self
5130 }
5131 pub fn push_dccp_pad(mut self, value: &[u8]) -> Self {
5132 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5133 self.as_rec_mut().extend(value);
5134 self
5135 }
5136}
5137impl<Prev: Rec> Drop for PushProtoinfoDccpAttrs<Prev> {
5138 fn drop(&mut self) {
5139 if let Some(prev) = &mut self.prev {
5140 if let Some(header_offset) = &self.header_offset {
5141 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5142 }
5143 }
5144 }
5145}
5146pub struct PushProtoinfoSctpAttrs<Prev: Rec> {
5147 pub(crate) prev: Option<Prev>,
5148 pub(crate) header_offset: Option<usize>,
5149}
5150impl<Prev: Rec> Rec for PushProtoinfoSctpAttrs<Prev> {
5151 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5152 self.prev.as_mut().unwrap().as_rec_mut()
5153 }
5154 fn as_rec(&self) -> &Vec<u8> {
5155 self.prev.as_ref().unwrap().as_rec()
5156 }
5157}
5158impl<Prev: Rec> PushProtoinfoSctpAttrs<Prev> {
5159 pub fn new(prev: Prev) -> Self {
5160 Self {
5161 prev: Some(prev),
5162 header_offset: None,
5163 }
5164 }
5165 pub fn end_nested(mut self) -> Prev {
5166 let mut prev = self.prev.take().unwrap();
5167 if let Some(header_offset) = &self.header_offset {
5168 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5169 }
5170 prev
5171 }
5172 #[doc = "sctp connection state\nAssociated type: \"NfCtSctpState\" (enum)"]
5173 pub fn push_sctp_state(mut self, value: u8) -> Self {
5174 push_header(self.as_rec_mut(), 1u16, 1 as u16);
5175 self.as_rec_mut().extend(value.to_ne_bytes());
5176 self
5177 }
5178 pub fn push_vtag_original(mut self, value: u32) -> Self {
5179 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5180 self.as_rec_mut().extend(value.to_be_bytes());
5181 self
5182 }
5183 pub fn push_vtag_reply(mut self, value: u32) -> Self {
5184 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5185 self.as_rec_mut().extend(value.to_be_bytes());
5186 self
5187 }
5188}
5189impl<Prev: Rec> Drop for PushProtoinfoSctpAttrs<Prev> {
5190 fn drop(&mut self) {
5191 if let Some(prev) = &mut self.prev {
5192 if let Some(header_offset) = &self.header_offset {
5193 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5194 }
5195 }
5196 }
5197}
5198pub struct PushProtoinfoAttrs<Prev: Rec> {
5199 pub(crate) prev: Option<Prev>,
5200 pub(crate) header_offset: Option<usize>,
5201}
5202impl<Prev: Rec> Rec for PushProtoinfoAttrs<Prev> {
5203 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5204 self.prev.as_mut().unwrap().as_rec_mut()
5205 }
5206 fn as_rec(&self) -> &Vec<u8> {
5207 self.prev.as_ref().unwrap().as_rec()
5208 }
5209}
5210impl<Prev: Rec> PushProtoinfoAttrs<Prev> {
5211 pub fn new(prev: Prev) -> Self {
5212 Self {
5213 prev: Some(prev),
5214 header_offset: None,
5215 }
5216 }
5217 pub fn end_nested(mut self) -> Prev {
5218 let mut prev = self.prev.take().unwrap();
5219 if let Some(header_offset) = &self.header_offset {
5220 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5221 }
5222 prev
5223 }
5224 #[doc = "conntrack tcp state information"]
5225 pub fn nested_protoinfo_tcp(mut self) -> PushProtoinfoTcpAttrs<Self> {
5226 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5227 PushProtoinfoTcpAttrs {
5228 prev: Some(self),
5229 header_offset: Some(header_offset),
5230 }
5231 }
5232 #[doc = "conntrack dccp state information"]
5233 pub fn nested_protoinfo_dccp(mut self) -> PushProtoinfoDccpAttrs<Self> {
5234 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5235 PushProtoinfoDccpAttrs {
5236 prev: Some(self),
5237 header_offset: Some(header_offset),
5238 }
5239 }
5240 #[doc = "conntrack sctp state information"]
5241 pub fn nested_protoinfo_sctp(mut self) -> PushProtoinfoSctpAttrs<Self> {
5242 let header_offset = push_nested_header(self.as_rec_mut(), 3u16);
5243 PushProtoinfoSctpAttrs {
5244 prev: Some(self),
5245 header_offset: Some(header_offset),
5246 }
5247 }
5248}
5249impl<Prev: Rec> Drop for PushProtoinfoAttrs<Prev> {
5250 fn drop(&mut self) {
5251 if let Some(prev) = &mut self.prev {
5252 if let Some(header_offset) = &self.header_offset {
5253 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5254 }
5255 }
5256 }
5257}
5258pub struct PushHelpAttrs<Prev: Rec> {
5259 pub(crate) prev: Option<Prev>,
5260 pub(crate) header_offset: Option<usize>,
5261}
5262impl<Prev: Rec> Rec for PushHelpAttrs<Prev> {
5263 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5264 self.prev.as_mut().unwrap().as_rec_mut()
5265 }
5266 fn as_rec(&self) -> &Vec<u8> {
5267 self.prev.as_ref().unwrap().as_rec()
5268 }
5269}
5270impl<Prev: Rec> PushHelpAttrs<Prev> {
5271 pub fn new(prev: Prev) -> Self {
5272 Self {
5273 prev: Some(prev),
5274 header_offset: None,
5275 }
5276 }
5277 pub fn end_nested(mut self) -> Prev {
5278 let mut prev = self.prev.take().unwrap();
5279 if let Some(header_offset) = &self.header_offset {
5280 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5281 }
5282 prev
5283 }
5284 #[doc = "helper name"]
5285 pub fn push_help_name(mut self, value: &CStr) -> Self {
5286 push_header(
5287 self.as_rec_mut(),
5288 1u16,
5289 value.to_bytes_with_nul().len() as u16,
5290 );
5291 self.as_rec_mut().extend(value.to_bytes_with_nul());
5292 self
5293 }
5294 #[doc = "helper name"]
5295 pub fn push_help_name_bytes(mut self, value: &[u8]) -> Self {
5296 push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5297 self.as_rec_mut().extend(value);
5298 self.as_rec_mut().push(0);
5299 self
5300 }
5301}
5302impl<Prev: Rec> Drop for PushHelpAttrs<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 PushNatProtoAttrs<Prev: Rec> {
5312 pub(crate) prev: Option<Prev>,
5313 pub(crate) header_offset: Option<usize>,
5314}
5315impl<Prev: Rec> Rec for PushNatProtoAttrs<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> PushNatProtoAttrs<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 pub fn push_nat_port_min(mut self, value: u16) -> Self {
5338 push_header(self.as_rec_mut(), 1u16, 2 as u16);
5339 self.as_rec_mut().extend(value.to_be_bytes());
5340 self
5341 }
5342 pub fn push_nat_port_max(mut self, value: u16) -> Self {
5343 push_header(self.as_rec_mut(), 2u16, 2 as u16);
5344 self.as_rec_mut().extend(value.to_be_bytes());
5345 self
5346 }
5347}
5348impl<Prev: Rec> Drop for PushNatProtoAttrs<Prev> {
5349 fn drop(&mut self) {
5350 if let Some(prev) = &mut self.prev {
5351 if let Some(header_offset) = &self.header_offset {
5352 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5353 }
5354 }
5355 }
5356}
5357pub struct PushNatAttrs<Prev: Rec> {
5358 pub(crate) prev: Option<Prev>,
5359 pub(crate) header_offset: Option<usize>,
5360}
5361impl<Prev: Rec> Rec for PushNatAttrs<Prev> {
5362 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5363 self.prev.as_mut().unwrap().as_rec_mut()
5364 }
5365 fn as_rec(&self) -> &Vec<u8> {
5366 self.prev.as_ref().unwrap().as_rec()
5367 }
5368}
5369impl<Prev: Rec> PushNatAttrs<Prev> {
5370 pub fn new(prev: Prev) -> Self {
5371 Self {
5372 prev: Some(prev),
5373 header_offset: None,
5374 }
5375 }
5376 pub fn end_nested(mut self) -> Prev {
5377 let mut prev = self.prev.take().unwrap();
5378 if let Some(header_offset) = &self.header_offset {
5379 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5380 }
5381 prev
5382 }
5383 pub fn push_nat_v4_minip(mut self, value: u32) -> Self {
5384 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5385 self.as_rec_mut().extend(value.to_be_bytes());
5386 self
5387 }
5388 pub fn push_nat_v4_maxip(mut self, value: u32) -> Self {
5389 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5390 self.as_rec_mut().extend(value.to_be_bytes());
5391 self
5392 }
5393 pub fn push_nat_v6_minip(mut self, value: &[u8]) -> Self {
5394 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
5395 self.as_rec_mut().extend(value);
5396 self
5397 }
5398 pub fn push_nat_v6_maxip(mut self, value: &[u8]) -> Self {
5399 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
5400 self.as_rec_mut().extend(value);
5401 self
5402 }
5403 pub fn nested_nat_proto(mut self) -> PushNatProtoAttrs<Self> {
5404 let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5405 PushNatProtoAttrs {
5406 prev: Some(self),
5407 header_offset: Some(header_offset),
5408 }
5409 }
5410}
5411impl<Prev: Rec> Drop for PushNatAttrs<Prev> {
5412 fn drop(&mut self) {
5413 if let Some(prev) = &mut self.prev {
5414 if let Some(header_offset) = &self.header_offset {
5415 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5416 }
5417 }
5418 }
5419}
5420pub struct PushSeqadjAttrs<Prev: Rec> {
5421 pub(crate) prev: Option<Prev>,
5422 pub(crate) header_offset: Option<usize>,
5423}
5424impl<Prev: Rec> Rec for PushSeqadjAttrs<Prev> {
5425 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5426 self.prev.as_mut().unwrap().as_rec_mut()
5427 }
5428 fn as_rec(&self) -> &Vec<u8> {
5429 self.prev.as_ref().unwrap().as_rec()
5430 }
5431}
5432impl<Prev: Rec> PushSeqadjAttrs<Prev> {
5433 pub fn new(prev: Prev) -> Self {
5434 Self {
5435 prev: Some(prev),
5436 header_offset: None,
5437 }
5438 }
5439 pub fn end_nested(mut self) -> Prev {
5440 let mut prev = self.prev.take().unwrap();
5441 if let Some(header_offset) = &self.header_offset {
5442 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5443 }
5444 prev
5445 }
5446 pub fn push_correction_pos(mut self, value: u32) -> Self {
5447 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5448 self.as_rec_mut().extend(value.to_be_bytes());
5449 self
5450 }
5451 pub fn push_offset_before(mut self, value: u32) -> Self {
5452 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5453 self.as_rec_mut().extend(value.to_be_bytes());
5454 self
5455 }
5456 pub fn push_offset_after(mut self, value: u32) -> Self {
5457 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5458 self.as_rec_mut().extend(value.to_be_bytes());
5459 self
5460 }
5461}
5462impl<Prev: Rec> Drop for PushSeqadjAttrs<Prev> {
5463 fn drop(&mut self) {
5464 if let Some(prev) = &mut self.prev {
5465 if let Some(header_offset) = &self.header_offset {
5466 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5467 }
5468 }
5469 }
5470}
5471pub struct PushSecctxAttrs<Prev: Rec> {
5472 pub(crate) prev: Option<Prev>,
5473 pub(crate) header_offset: Option<usize>,
5474}
5475impl<Prev: Rec> Rec for PushSecctxAttrs<Prev> {
5476 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5477 self.prev.as_mut().unwrap().as_rec_mut()
5478 }
5479 fn as_rec(&self) -> &Vec<u8> {
5480 self.prev.as_ref().unwrap().as_rec()
5481 }
5482}
5483impl<Prev: Rec> PushSecctxAttrs<Prev> {
5484 pub fn new(prev: Prev) -> Self {
5485 Self {
5486 prev: Some(prev),
5487 header_offset: None,
5488 }
5489 }
5490 pub fn end_nested(mut self) -> Prev {
5491 let mut prev = self.prev.take().unwrap();
5492 if let Some(header_offset) = &self.header_offset {
5493 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5494 }
5495 prev
5496 }
5497 pub fn push_secctx_name(mut self, value: &CStr) -> Self {
5498 push_header(
5499 self.as_rec_mut(),
5500 1u16,
5501 value.to_bytes_with_nul().len() as u16,
5502 );
5503 self.as_rec_mut().extend(value.to_bytes_with_nul());
5504 self
5505 }
5506 pub fn push_secctx_name_bytes(mut self, value: &[u8]) -> Self {
5507 push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
5508 self.as_rec_mut().extend(value);
5509 self.as_rec_mut().push(0);
5510 self
5511 }
5512}
5513impl<Prev: Rec> Drop for PushSecctxAttrs<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 PushSynproxyAttrs<Prev: Rec> {
5523 pub(crate) prev: Option<Prev>,
5524 pub(crate) header_offset: Option<usize>,
5525}
5526impl<Prev: Rec> Rec for PushSynproxyAttrs<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> PushSynproxyAttrs<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_isn(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_its(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_tsoff(mut self, value: u32) -> Self {
5559 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5560 self.as_rec_mut().extend(value.to_be_bytes());
5561 self
5562 }
5563}
5564impl<Prev: Rec> Drop for PushSynproxyAttrs<Prev> {
5565 fn drop(&mut self) {
5566 if let Some(prev) = &mut self.prev {
5567 if let Some(header_offset) = &self.header_offset {
5568 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5569 }
5570 }
5571 }
5572}
5573pub struct PushConntrackAttrs<Prev: Rec> {
5574 pub(crate) prev: Option<Prev>,
5575 pub(crate) header_offset: Option<usize>,
5576}
5577impl<Prev: Rec> Rec for PushConntrackAttrs<Prev> {
5578 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5579 self.prev.as_mut().unwrap().as_rec_mut()
5580 }
5581 fn as_rec(&self) -> &Vec<u8> {
5582 self.prev.as_ref().unwrap().as_rec()
5583 }
5584}
5585impl<Prev: Rec> PushConntrackAttrs<Prev> {
5586 pub fn new(prev: Prev) -> Self {
5587 Self {
5588 prev: Some(prev),
5589 header_offset: None,
5590 }
5591 }
5592 pub fn end_nested(mut self) -> Prev {
5593 let mut prev = self.prev.take().unwrap();
5594 if let Some(header_offset) = &self.header_offset {
5595 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5596 }
5597 prev
5598 }
5599 #[doc = "conntrack l3+l4 protocol information, original direction"]
5600 pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
5601 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
5602 PushTupleAttrs {
5603 prev: Some(self),
5604 header_offset: Some(header_offset),
5605 }
5606 }
5607 #[doc = "conntrack l3+l4 protocol information, reply direction"]
5608 pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
5609 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
5610 PushTupleAttrs {
5611 prev: Some(self),
5612 header_offset: Some(header_offset),
5613 }
5614 }
5615 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
5616 pub fn push_status(mut self, value: u32) -> Self {
5617 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5618 self.as_rec_mut().extend(value.to_be_bytes());
5619 self
5620 }
5621 pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
5622 let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
5623 PushProtoinfoAttrs {
5624 prev: Some(self),
5625 header_offset: Some(header_offset),
5626 }
5627 }
5628 pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
5629 let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
5630 PushHelpAttrs {
5631 prev: Some(self),
5632 header_offset: Some(header_offset),
5633 }
5634 }
5635 pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
5636 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
5637 PushNatAttrs {
5638 prev: Some(self),
5639 header_offset: Some(header_offset),
5640 }
5641 }
5642 pub fn push_timeout(mut self, value: u32) -> Self {
5643 push_header(self.as_rec_mut(), 7u16, 4 as u16);
5644 self.as_rec_mut().extend(value.to_be_bytes());
5645 self
5646 }
5647 pub fn push_mark(mut self, value: u32) -> Self {
5648 push_header(self.as_rec_mut(), 8u16, 4 as u16);
5649 self.as_rec_mut().extend(value.to_be_bytes());
5650 self
5651 }
5652 pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
5653 let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
5654 PushCounterAttrs {
5655 prev: Some(self),
5656 header_offset: Some(header_offset),
5657 }
5658 }
5659 pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
5660 let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
5661 PushCounterAttrs {
5662 prev: Some(self),
5663 header_offset: Some(header_offset),
5664 }
5665 }
5666 pub fn push_use(mut self, value: u32) -> Self {
5667 push_header(self.as_rec_mut(), 11u16, 4 as u16);
5668 self.as_rec_mut().extend(value.to_be_bytes());
5669 self
5670 }
5671 pub fn push_id(mut self, value: u32) -> Self {
5672 push_header(self.as_rec_mut(), 12u16, 4 as u16);
5673 self.as_rec_mut().extend(value.to_be_bytes());
5674 self
5675 }
5676 pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
5677 let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
5678 PushNatAttrs {
5679 prev: Some(self),
5680 header_offset: Some(header_offset),
5681 }
5682 }
5683 pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
5684 let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
5685 PushTupleAttrs {
5686 prev: Some(self),
5687 header_offset: Some(header_offset),
5688 }
5689 }
5690 pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
5691 let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
5692 PushSeqadjAttrs {
5693 prev: Some(self),
5694 header_offset: Some(header_offset),
5695 }
5696 }
5697 pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
5698 let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
5699 PushSeqadjAttrs {
5700 prev: Some(self),
5701 header_offset: Some(header_offset),
5702 }
5703 }
5704 #[doc = "obsolete"]
5705 pub fn push_secmark(mut self, value: &[u8]) -> Self {
5706 push_header(self.as_rec_mut(), 17u16, value.len() as u16);
5707 self.as_rec_mut().extend(value);
5708 self
5709 }
5710 #[doc = "conntrack zone id"]
5711 pub fn push_zone(mut self, value: u16) -> Self {
5712 push_header(self.as_rec_mut(), 18u16, 2 as u16);
5713 self.as_rec_mut().extend(value.to_be_bytes());
5714 self
5715 }
5716 pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
5717 let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
5718 PushSecctxAttrs {
5719 prev: Some(self),
5720 header_offset: Some(header_offset),
5721 }
5722 }
5723 pub fn push_timestamp(mut self, value: u64) -> Self {
5724 push_header(self.as_rec_mut(), 20u16, 8 as u16);
5725 self.as_rec_mut().extend(value.to_be_bytes());
5726 self
5727 }
5728 pub fn push_mark_mask(mut self, value: u32) -> Self {
5729 push_header(self.as_rec_mut(), 21u16, 4 as u16);
5730 self.as_rec_mut().extend(value.to_be_bytes());
5731 self
5732 }
5733 pub fn push_labels(mut self, value: &[u8]) -> Self {
5734 push_header(self.as_rec_mut(), 22u16, value.len() as u16);
5735 self.as_rec_mut().extend(value);
5736 self
5737 }
5738 pub fn push_labels_mask(mut self, value: &[u8]) -> Self {
5739 push_header(self.as_rec_mut(), 23u16, value.len() as u16);
5740 self.as_rec_mut().extend(value);
5741 self
5742 }
5743 pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
5744 let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
5745 PushSynproxyAttrs {
5746 prev: Some(self),
5747 header_offset: Some(header_offset),
5748 }
5749 }
5750 pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
5751 let header_offset = push_nested_header(self.as_rec_mut(), 25u16);
5752 PushTupleAttrs {
5753 prev: Some(self),
5754 header_offset: Some(header_offset),
5755 }
5756 }
5757 #[doc = "conntrack flag bits to change\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
5758 pub fn push_status_mask(mut self, value: u32) -> Self {
5759 push_header(self.as_rec_mut(), 26u16, 4 as u16);
5760 self.as_rec_mut().extend(value.to_be_bytes());
5761 self
5762 }
5763 pub fn push_timestamp_event(mut self, value: u64) -> Self {
5764 push_header(self.as_rec_mut(), 27u16, 8 as u16);
5765 self.as_rec_mut().extend(value.to_be_bytes());
5766 self
5767 }
5768}
5769impl<Prev: Rec> Drop for PushConntrackAttrs<Prev> {
5770 fn drop(&mut self) {
5771 if let Some(prev) = &mut self.prev {
5772 if let Some(header_offset) = &self.header_offset {
5773 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5774 }
5775 }
5776 }
5777}
5778pub struct PushConntrackStatsAttrs<Prev: Rec> {
5779 pub(crate) prev: Option<Prev>,
5780 pub(crate) header_offset: Option<usize>,
5781}
5782impl<Prev: Rec> Rec for PushConntrackStatsAttrs<Prev> {
5783 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5784 self.prev.as_mut().unwrap().as_rec_mut()
5785 }
5786 fn as_rec(&self) -> &Vec<u8> {
5787 self.prev.as_ref().unwrap().as_rec()
5788 }
5789}
5790impl<Prev: Rec> PushConntrackStatsAttrs<Prev> {
5791 pub fn new(prev: Prev) -> Self {
5792 Self {
5793 prev: Some(prev),
5794 header_offset: None,
5795 }
5796 }
5797 pub fn end_nested(mut self) -> Prev {
5798 let mut prev = self.prev.take().unwrap();
5799 if let Some(header_offset) = &self.header_offset {
5800 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5801 }
5802 prev
5803 }
5804 #[doc = "obsolete"]
5805 pub fn push_searched(mut self, value: u32) -> Self {
5806 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5807 self.as_rec_mut().extend(value.to_be_bytes());
5808 self
5809 }
5810 pub fn push_found(mut self, value: u32) -> Self {
5811 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5812 self.as_rec_mut().extend(value.to_be_bytes());
5813 self
5814 }
5815 #[doc = "obsolete"]
5816 pub fn push_new(mut self, value: u32) -> Self {
5817 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5818 self.as_rec_mut().extend(value.to_be_bytes());
5819 self
5820 }
5821 #[doc = "obsolete"]
5822 pub fn push_invalid(mut self, value: u32) -> Self {
5823 push_header(self.as_rec_mut(), 4u16, 4 as u16);
5824 self.as_rec_mut().extend(value.to_be_bytes());
5825 self
5826 }
5827 #[doc = "obsolete"]
5828 pub fn push_ignore(mut self, value: u32) -> Self {
5829 push_header(self.as_rec_mut(), 5u16, 4 as u16);
5830 self.as_rec_mut().extend(value.to_be_bytes());
5831 self
5832 }
5833 #[doc = "obsolete"]
5834 pub fn push_delete(mut self, value: u32) -> Self {
5835 push_header(self.as_rec_mut(), 6u16, 4 as u16);
5836 self.as_rec_mut().extend(value.to_be_bytes());
5837 self
5838 }
5839 #[doc = "obsolete"]
5840 pub fn push_delete_list(mut self, value: u32) -> Self {
5841 push_header(self.as_rec_mut(), 7u16, 4 as u16);
5842 self.as_rec_mut().extend(value.to_be_bytes());
5843 self
5844 }
5845 pub fn push_insert(mut self, value: u32) -> Self {
5846 push_header(self.as_rec_mut(), 8u16, 4 as u16);
5847 self.as_rec_mut().extend(value.to_be_bytes());
5848 self
5849 }
5850 pub fn push_insert_failed(mut self, value: u32) -> Self {
5851 push_header(self.as_rec_mut(), 9u16, 4 as u16);
5852 self.as_rec_mut().extend(value.to_be_bytes());
5853 self
5854 }
5855 pub fn push_drop(mut self, value: u32) -> Self {
5856 push_header(self.as_rec_mut(), 10u16, 4 as u16);
5857 self.as_rec_mut().extend(value.to_be_bytes());
5858 self
5859 }
5860 pub fn push_early_drop(mut self, value: u32) -> Self {
5861 push_header(self.as_rec_mut(), 11u16, 4 as u16);
5862 self.as_rec_mut().extend(value.to_be_bytes());
5863 self
5864 }
5865 pub fn push_error(mut self, value: u32) -> Self {
5866 push_header(self.as_rec_mut(), 12u16, 4 as u16);
5867 self.as_rec_mut().extend(value.to_be_bytes());
5868 self
5869 }
5870 pub fn push_search_restart(mut self, value: u32) -> Self {
5871 push_header(self.as_rec_mut(), 13u16, 4 as u16);
5872 self.as_rec_mut().extend(value.to_be_bytes());
5873 self
5874 }
5875 pub fn push_clash_resolve(mut self, value: u32) -> Self {
5876 push_header(self.as_rec_mut(), 14u16, 4 as u16);
5877 self.as_rec_mut().extend(value.to_be_bytes());
5878 self
5879 }
5880 pub fn push_chain_toolong(mut self, value: u32) -> Self {
5881 push_header(self.as_rec_mut(), 15u16, 4 as u16);
5882 self.as_rec_mut().extend(value.to_be_bytes());
5883 self
5884 }
5885}
5886impl<Prev: Rec> Drop for PushConntrackStatsAttrs<Prev> {
5887 fn drop(&mut self) {
5888 if let Some(prev) = &mut self.prev {
5889 if let Some(header_offset) = &self.header_offset {
5890 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5891 }
5892 }
5893 }
5894}
5895#[derive(Clone)]
5896pub struct PushNfgenmsg {
5897 pub(crate) buf: [u8; 4usize],
5898}
5899#[doc = "Create zero-initialized struct"]
5900impl Default for PushNfgenmsg {
5901 fn default() -> Self {
5902 Self { buf: [0u8; 4usize] }
5903 }
5904}
5905impl PushNfgenmsg {
5906 #[doc = "Create zero-initialized struct"]
5907 pub fn new() -> Self {
5908 Default::default()
5909 }
5910 #[doc = "Copy from contents from other slice"]
5911 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
5912 if other.len() != Self::len() {
5913 return None;
5914 }
5915 let mut buf = [0u8; Self::len()];
5916 buf.clone_from_slice(other);
5917 Some(Self { buf })
5918 }
5919 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
5920 pub fn new_from_zeroed(other: &[u8]) -> Self {
5921 let mut buf = [0u8; Self::len()];
5922 let len = buf.len().min(other.len());
5923 buf[..len].clone_from_slice(&other[..len]);
5924 Self { buf }
5925 }
5926 pub fn as_slice(&self) -> &[u8] {
5927 &self.buf
5928 }
5929 pub fn as_mut_slice(&mut self) -> &mut [u8] {
5930 &mut self.buf
5931 }
5932 pub const fn len() -> usize {
5933 4usize
5934 }
5935 pub fn nfgen_family(&self) -> u8 {
5936 parse_u8(&self.buf[0usize..1usize]).unwrap()
5937 }
5938 pub fn set_nfgen_family(&mut self, value: u8) {
5939 self.buf[0usize..1usize].copy_from_slice(&value.to_ne_bytes())
5940 }
5941 pub fn version(&self) -> u8 {
5942 parse_u8(&self.buf[1usize..2usize]).unwrap()
5943 }
5944 pub fn set_version(&mut self, value: u8) {
5945 self.buf[1usize..2usize].copy_from_slice(&value.to_ne_bytes())
5946 }
5947 pub fn res_id(&self) -> u16 {
5948 parse_be_u16(&self.buf[2usize..4usize]).unwrap()
5949 }
5950 pub fn set_res_id(&mut self, value: u16) {
5951 self.buf[2usize..4usize].copy_from_slice(&value.to_be_bytes())
5952 }
5953}
5954impl std::fmt::Debug for PushNfgenmsg {
5955 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5956 fmt.debug_struct("Nfgenmsg")
5957 .field("nfgen_family", &self.nfgen_family())
5958 .field("version", &self.version())
5959 .field("res_id", &self.res_id())
5960 .finish()
5961 }
5962}
5963#[derive(Clone)]
5964pub struct PushNfCtTcpFlagsMask {
5965 pub(crate) buf: [u8; 2usize],
5966}
5967#[doc = "Create zero-initialized struct"]
5968impl Default for PushNfCtTcpFlagsMask {
5969 fn default() -> Self {
5970 Self { buf: [0u8; 2usize] }
5971 }
5972}
5973impl PushNfCtTcpFlagsMask {
5974 #[doc = "Create zero-initialized struct"]
5975 pub fn new() -> Self {
5976 Default::default()
5977 }
5978 #[doc = "Copy from contents from other slice"]
5979 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
5980 if other.len() != Self::len() {
5981 return None;
5982 }
5983 let mut buf = [0u8; Self::len()];
5984 buf.clone_from_slice(other);
5985 Some(Self { buf })
5986 }
5987 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
5988 pub fn new_from_zeroed(other: &[u8]) -> Self {
5989 let mut buf = [0u8; Self::len()];
5990 let len = buf.len().min(other.len());
5991 buf[..len].clone_from_slice(&other[..len]);
5992 Self { buf }
5993 }
5994 pub fn as_slice(&self) -> &[u8] {
5995 &self.buf
5996 }
5997 pub fn as_mut_slice(&mut self) -> &mut [u8] {
5998 &mut self.buf
5999 }
6000 pub const fn len() -> usize {
6001 2usize
6002 }
6003 #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6004 pub fn flags(&self) -> u8 {
6005 parse_u8(&self.buf[0usize..1usize]).unwrap()
6006 }
6007 #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6008 pub fn set_flags(&mut self, value: u8) {
6009 self.buf[0usize..1usize].copy_from_slice(&value.to_ne_bytes())
6010 }
6011 #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6012 pub fn mask(&self) -> u8 {
6013 parse_u8(&self.buf[1usize..2usize]).unwrap()
6014 }
6015 #[doc = "Associated type: \"NfCtTcpFlags\" (1 bit per enumeration)"]
6016 pub fn set_mask(&mut self, value: u8) {
6017 self.buf[1usize..2usize].copy_from_slice(&value.to_ne_bytes())
6018 }
6019}
6020impl std::fmt::Debug for PushNfCtTcpFlagsMask {
6021 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6022 fmt.debug_struct("NfCtTcpFlagsMask")
6023 .field(
6024 "flags",
6025 &FormatFlags(self.flags().into(), NfCtTcpFlags::from_value),
6026 )
6027 .field(
6028 "mask",
6029 &FormatFlags(self.mask().into(), NfCtTcpFlags::from_value),
6030 )
6031 .finish()
6032 }
6033}
6034#[doc = "get / dump entries"]
6035pub struct PushOpGetDumpRequest<Prev: Rec> {
6036 pub(crate) prev: Option<Prev>,
6037 pub(crate) header_offset: Option<usize>,
6038}
6039impl<Prev: Rec> Rec for PushOpGetDumpRequest<Prev> {
6040 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6041 self.prev.as_mut().unwrap().as_rec_mut()
6042 }
6043 fn as_rec(&self) -> &Vec<u8> {
6044 self.prev.as_ref().unwrap().as_rec()
6045 }
6046}
6047impl<Prev: Rec> PushOpGetDumpRequest<Prev> {
6048 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
6049 Self::write_header(&mut prev, header);
6050 Self::new_without_header(prev)
6051 }
6052 fn new_without_header(prev: Prev) -> Self {
6053 Self {
6054 prev: Some(prev),
6055 header_offset: None,
6056 }
6057 }
6058 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
6059 prev.as_rec_mut().extend(header.as_slice());
6060 }
6061 pub fn end_nested(mut self) -> Prev {
6062 let mut prev = self.prev.take().unwrap();
6063 if let Some(header_offset) = &self.header_offset {
6064 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6065 }
6066 prev
6067 }
6068 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6069 pub fn push_status(mut self, value: u32) -> Self {
6070 push_header(self.as_rec_mut(), 3u16, 4 as u16);
6071 self.as_rec_mut().extend(value.to_be_bytes());
6072 self
6073 }
6074 pub fn push_mark(mut self, value: u32) -> Self {
6075 push_header(self.as_rec_mut(), 8u16, 4 as u16);
6076 self.as_rec_mut().extend(value.to_be_bytes());
6077 self
6078 }
6079 #[doc = "conntrack zone id"]
6080 pub fn push_zone(mut self, value: u16) -> Self {
6081 push_header(self.as_rec_mut(), 18u16, 2 as u16);
6082 self.as_rec_mut().extend(value.to_be_bytes());
6083 self
6084 }
6085 pub fn nested_filter(mut self) -> PushTupleAttrs<Self> {
6086 let header_offset = push_nested_header(self.as_rec_mut(), 25u16);
6087 PushTupleAttrs {
6088 prev: Some(self),
6089 header_offset: Some(header_offset),
6090 }
6091 }
6092}
6093impl<Prev: Rec> Drop for PushOpGetDumpRequest<Prev> {
6094 fn drop(&mut self) {
6095 if let Some(prev) = &mut self.prev {
6096 if let Some(header_offset) = &self.header_offset {
6097 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6098 }
6099 }
6100 }
6101}
6102#[doc = "get / dump entries"]
6103#[derive(Clone)]
6104pub enum OpGetDumpRequest<'a> {
6105 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6106 Status(u32),
6107 Mark(u32),
6108 #[doc = "conntrack zone id"]
6109 Zone(u16),
6110 Filter(IterableTupleAttrs<'a>),
6111}
6112impl<'a> IterableOpGetDumpRequest<'a> {
6113 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6114 pub fn get_status(&self) -> Result<u32, ErrorContext> {
6115 let mut iter = self.clone();
6116 iter.pos = 0;
6117 for attr in iter {
6118 if let OpGetDumpRequest::Status(val) = attr? {
6119 return Ok(val);
6120 }
6121 }
6122 Err(ErrorContext::new_missing(
6123 "OpGetDumpRequest",
6124 "Status",
6125 self.orig_loc,
6126 self.buf.as_ptr() as usize,
6127 ))
6128 }
6129 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
6130 let mut iter = self.clone();
6131 iter.pos = 0;
6132 for attr in iter {
6133 if let OpGetDumpRequest::Mark(val) = attr? {
6134 return Ok(val);
6135 }
6136 }
6137 Err(ErrorContext::new_missing(
6138 "OpGetDumpRequest",
6139 "Mark",
6140 self.orig_loc,
6141 self.buf.as_ptr() as usize,
6142 ))
6143 }
6144 #[doc = "conntrack zone id"]
6145 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
6146 let mut iter = self.clone();
6147 iter.pos = 0;
6148 for attr in iter {
6149 if let OpGetDumpRequest::Zone(val) = attr? {
6150 return Ok(val);
6151 }
6152 }
6153 Err(ErrorContext::new_missing(
6154 "OpGetDumpRequest",
6155 "Zone",
6156 self.orig_loc,
6157 self.buf.as_ptr() as usize,
6158 ))
6159 }
6160 pub fn get_filter(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6161 let mut iter = self.clone();
6162 iter.pos = 0;
6163 for attr in iter {
6164 if let OpGetDumpRequest::Filter(val) = attr? {
6165 return Ok(val);
6166 }
6167 }
6168 Err(ErrorContext::new_missing(
6169 "OpGetDumpRequest",
6170 "Filter",
6171 self.orig_loc,
6172 self.buf.as_ptr() as usize,
6173 ))
6174 }
6175}
6176impl OpGetDumpRequest<'_> {
6177 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDumpRequest<'a>) {
6178 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
6179 (
6180 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
6181 IterableOpGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize),
6182 )
6183 }
6184 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6185 ConntrackAttrs::attr_from_type(r#type)
6186 }
6187}
6188#[derive(Clone, Copy, Default)]
6189pub struct IterableOpGetDumpRequest<'a> {
6190 buf: &'a [u8],
6191 pos: usize,
6192 orig_loc: usize,
6193}
6194impl<'a> IterableOpGetDumpRequest<'a> {
6195 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6196 Self {
6197 buf,
6198 pos: 0,
6199 orig_loc,
6200 }
6201 }
6202 pub fn get_buf(&self) -> &'a [u8] {
6203 self.buf
6204 }
6205}
6206impl<'a> Iterator for IterableOpGetDumpRequest<'a> {
6207 type Item = Result<OpGetDumpRequest<'a>, ErrorContext>;
6208 fn next(&mut self) -> Option<Self::Item> {
6209 let pos = self.pos;
6210 let mut r#type;
6211 loop {
6212 r#type = None;
6213 if self.buf.len() == self.pos {
6214 return None;
6215 }
6216 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6217 break;
6218 };
6219 r#type = Some(header.r#type);
6220 let res = match header.r#type {
6221 3u16 => OpGetDumpRequest::Status({
6222 let res = parse_be_u32(next);
6223 let Some(val) = res else { break };
6224 val
6225 }),
6226 8u16 => OpGetDumpRequest::Mark({
6227 let res = parse_be_u32(next);
6228 let Some(val) = res else { break };
6229 val
6230 }),
6231 18u16 => OpGetDumpRequest::Zone({
6232 let res = parse_be_u16(next);
6233 let Some(val) = res else { break };
6234 val
6235 }),
6236 25u16 => OpGetDumpRequest::Filter({
6237 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6238 let Some(val) = res else { break };
6239 val
6240 }),
6241 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6242 n => continue,
6243 };
6244 return Some(Ok(res));
6245 }
6246 Some(Err(ErrorContext::new(
6247 "OpGetDumpRequest",
6248 r#type.and_then(|t| OpGetDumpRequest::attr_from_type(t)),
6249 self.orig_loc,
6250 self.buf.as_ptr().wrapping_add(pos) as usize,
6251 )))
6252 }
6253}
6254impl<'a> std::fmt::Debug for IterableOpGetDumpRequest<'_> {
6255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6256 let mut fmt = f.debug_struct("OpGetDumpRequest");
6257 for attr in self.clone() {
6258 let attr = match attr {
6259 Ok(a) => a,
6260 Err(err) => {
6261 fmt.finish()?;
6262 f.write_str("Err(")?;
6263 err.fmt(f)?;
6264 return f.write_str(")");
6265 }
6266 };
6267 match attr {
6268 OpGetDumpRequest::Status(val) => {
6269 fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
6270 }
6271 OpGetDumpRequest::Mark(val) => fmt.field("Mark", &val),
6272 OpGetDumpRequest::Zone(val) => fmt.field("Zone", &val),
6273 OpGetDumpRequest::Filter(val) => fmt.field("Filter", &val),
6274 };
6275 }
6276 fmt.finish()
6277 }
6278}
6279impl IterableOpGetDumpRequest<'_> {
6280 pub fn lookup_attr(
6281 &self,
6282 offset: usize,
6283 missing_type: Option<u16>,
6284 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6285 let mut stack = Vec::new();
6286 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6287 if cur == offset + PushNfgenmsg::len() {
6288 stack.push(("OpGetDumpRequest", offset));
6289 return (
6290 stack,
6291 missing_type.and_then(|t| OpGetDumpRequest::attr_from_type(t)),
6292 );
6293 }
6294 if cur > offset || cur + self.buf.len() < offset {
6295 return (stack, None);
6296 }
6297 let mut attrs = self.clone();
6298 let mut last_off = cur + attrs.pos;
6299 let mut missing = None;
6300 while let Some(attr) = attrs.next() {
6301 let Ok(attr) = attr else { break };
6302 match attr {
6303 OpGetDumpRequest::Status(val) => {
6304 if last_off == offset {
6305 stack.push(("Status", last_off));
6306 break;
6307 }
6308 }
6309 OpGetDumpRequest::Mark(val) => {
6310 if last_off == offset {
6311 stack.push(("Mark", last_off));
6312 break;
6313 }
6314 }
6315 OpGetDumpRequest::Zone(val) => {
6316 if last_off == offset {
6317 stack.push(("Zone", last_off));
6318 break;
6319 }
6320 }
6321 OpGetDumpRequest::Filter(val) => {
6322 (stack, missing) = val.lookup_attr(offset, missing_type);
6323 if !stack.is_empty() {
6324 break;
6325 }
6326 }
6327 _ => {}
6328 };
6329 last_off = cur + attrs.pos;
6330 }
6331 if !stack.is_empty() {
6332 stack.push(("OpGetDumpRequest", cur));
6333 }
6334 (stack, missing)
6335 }
6336}
6337#[doc = "get / dump entries"]
6338pub struct PushOpGetDumpReply<Prev: Rec> {
6339 pub(crate) prev: Option<Prev>,
6340 pub(crate) header_offset: Option<usize>,
6341}
6342impl<Prev: Rec> Rec for PushOpGetDumpReply<Prev> {
6343 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6344 self.prev.as_mut().unwrap().as_rec_mut()
6345 }
6346 fn as_rec(&self) -> &Vec<u8> {
6347 self.prev.as_ref().unwrap().as_rec()
6348 }
6349}
6350impl<Prev: Rec> PushOpGetDumpReply<Prev> {
6351 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
6352 Self::write_header(&mut prev, header);
6353 Self::new_without_header(prev)
6354 }
6355 fn new_without_header(prev: Prev) -> Self {
6356 Self {
6357 prev: Some(prev),
6358 header_offset: None,
6359 }
6360 }
6361 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
6362 prev.as_rec_mut().extend(header.as_slice());
6363 }
6364 pub fn end_nested(mut self) -> Prev {
6365 let mut prev = self.prev.take().unwrap();
6366 if let Some(header_offset) = &self.header_offset {
6367 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6368 }
6369 prev
6370 }
6371 #[doc = "conntrack l3+l4 protocol information, original direction"]
6372 pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
6373 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
6374 PushTupleAttrs {
6375 prev: Some(self),
6376 header_offset: Some(header_offset),
6377 }
6378 }
6379 #[doc = "conntrack l3+l4 protocol information, reply direction"]
6380 pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
6381 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
6382 PushTupleAttrs {
6383 prev: Some(self),
6384 header_offset: Some(header_offset),
6385 }
6386 }
6387 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6388 pub fn push_status(mut self, value: u32) -> Self {
6389 push_header(self.as_rec_mut(), 3u16, 4 as u16);
6390 self.as_rec_mut().extend(value.to_be_bytes());
6391 self
6392 }
6393 pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
6394 let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
6395 PushProtoinfoAttrs {
6396 prev: Some(self),
6397 header_offset: Some(header_offset),
6398 }
6399 }
6400 pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
6401 let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
6402 PushHelpAttrs {
6403 prev: Some(self),
6404 header_offset: Some(header_offset),
6405 }
6406 }
6407 pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
6408 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
6409 PushNatAttrs {
6410 prev: Some(self),
6411 header_offset: Some(header_offset),
6412 }
6413 }
6414 pub fn push_timeout(mut self, value: u32) -> Self {
6415 push_header(self.as_rec_mut(), 7u16, 4 as u16);
6416 self.as_rec_mut().extend(value.to_be_bytes());
6417 self
6418 }
6419 pub fn push_mark(mut self, value: u32) -> Self {
6420 push_header(self.as_rec_mut(), 8u16, 4 as u16);
6421 self.as_rec_mut().extend(value.to_be_bytes());
6422 self
6423 }
6424 pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
6425 let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
6426 PushCounterAttrs {
6427 prev: Some(self),
6428 header_offset: Some(header_offset),
6429 }
6430 }
6431 pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
6432 let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
6433 PushCounterAttrs {
6434 prev: Some(self),
6435 header_offset: Some(header_offset),
6436 }
6437 }
6438 pub fn push_use(mut self, value: u32) -> Self {
6439 push_header(self.as_rec_mut(), 11u16, 4 as u16);
6440 self.as_rec_mut().extend(value.to_be_bytes());
6441 self
6442 }
6443 pub fn push_id(mut self, value: u32) -> Self {
6444 push_header(self.as_rec_mut(), 12u16, 4 as u16);
6445 self.as_rec_mut().extend(value.to_be_bytes());
6446 self
6447 }
6448 pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
6449 let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
6450 PushNatAttrs {
6451 prev: Some(self),
6452 header_offset: Some(header_offset),
6453 }
6454 }
6455 pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
6456 let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
6457 PushTupleAttrs {
6458 prev: Some(self),
6459 header_offset: Some(header_offset),
6460 }
6461 }
6462 pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
6463 let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
6464 PushSeqadjAttrs {
6465 prev: Some(self),
6466 header_offset: Some(header_offset),
6467 }
6468 }
6469 pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
6470 let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
6471 PushSeqadjAttrs {
6472 prev: Some(self),
6473 header_offset: Some(header_offset),
6474 }
6475 }
6476 #[doc = "conntrack zone id"]
6477 pub fn push_zone(mut self, value: u16) -> Self {
6478 push_header(self.as_rec_mut(), 18u16, 2 as u16);
6479 self.as_rec_mut().extend(value.to_be_bytes());
6480 self
6481 }
6482 pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
6483 let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
6484 PushSecctxAttrs {
6485 prev: Some(self),
6486 header_offset: Some(header_offset),
6487 }
6488 }
6489 pub fn push_labels(mut self, value: &[u8]) -> Self {
6490 push_header(self.as_rec_mut(), 22u16, value.len() as u16);
6491 self.as_rec_mut().extend(value);
6492 self
6493 }
6494 pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
6495 let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
6496 PushSynproxyAttrs {
6497 prev: Some(self),
6498 header_offset: Some(header_offset),
6499 }
6500 }
6501}
6502impl<Prev: Rec> Drop for PushOpGetDumpReply<Prev> {
6503 fn drop(&mut self) {
6504 if let Some(prev) = &mut self.prev {
6505 if let Some(header_offset) = &self.header_offset {
6506 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6507 }
6508 }
6509 }
6510}
6511#[doc = "get / dump entries"]
6512#[derive(Clone)]
6513pub enum OpGetDumpReply<'a> {
6514 #[doc = "conntrack l3+l4 protocol information, original direction"]
6515 TupleOrig(IterableTupleAttrs<'a>),
6516 #[doc = "conntrack l3+l4 protocol information, reply direction"]
6517 TupleReply(IterableTupleAttrs<'a>),
6518 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6519 Status(u32),
6520 Protoinfo(IterableProtoinfoAttrs<'a>),
6521 Help(IterableHelpAttrs<'a>),
6522 NatSrc(IterableNatAttrs<'a>),
6523 Timeout(u32),
6524 Mark(u32),
6525 CountersOrig(IterableCounterAttrs<'a>),
6526 CountersReply(IterableCounterAttrs<'a>),
6527 Use(u32),
6528 Id(u32),
6529 NatDst(IterableNatAttrs<'a>),
6530 TupleMaster(IterableTupleAttrs<'a>),
6531 SeqAdjOrig(IterableSeqadjAttrs<'a>),
6532 SeqAdjReply(IterableSeqadjAttrs<'a>),
6533 #[doc = "conntrack zone id"]
6534 Zone(u16),
6535 Secctx(IterableSecctxAttrs<'a>),
6536 Labels(&'a [u8]),
6537 Synproxy(IterableSynproxyAttrs<'a>),
6538}
6539impl<'a> IterableOpGetDumpReply<'a> {
6540 #[doc = "conntrack l3+l4 protocol information, original direction"]
6541 pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6542 let mut iter = self.clone();
6543 iter.pos = 0;
6544 for attr in iter {
6545 if let OpGetDumpReply::TupleOrig(val) = attr? {
6546 return Ok(val);
6547 }
6548 }
6549 Err(ErrorContext::new_missing(
6550 "OpGetDumpReply",
6551 "TupleOrig",
6552 self.orig_loc,
6553 self.buf.as_ptr() as usize,
6554 ))
6555 }
6556 #[doc = "conntrack l3+l4 protocol information, reply direction"]
6557 pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6558 let mut iter = self.clone();
6559 iter.pos = 0;
6560 for attr in iter {
6561 if let OpGetDumpReply::TupleReply(val) = attr? {
6562 return Ok(val);
6563 }
6564 }
6565 Err(ErrorContext::new_missing(
6566 "OpGetDumpReply",
6567 "TupleReply",
6568 self.orig_loc,
6569 self.buf.as_ptr() as usize,
6570 ))
6571 }
6572 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
6573 pub fn get_status(&self) -> Result<u32, ErrorContext> {
6574 let mut iter = self.clone();
6575 iter.pos = 0;
6576 for attr in iter {
6577 if let OpGetDumpReply::Status(val) = attr? {
6578 return Ok(val);
6579 }
6580 }
6581 Err(ErrorContext::new_missing(
6582 "OpGetDumpReply",
6583 "Status",
6584 self.orig_loc,
6585 self.buf.as_ptr() as usize,
6586 ))
6587 }
6588 pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
6589 let mut iter = self.clone();
6590 iter.pos = 0;
6591 for attr in iter {
6592 if let OpGetDumpReply::Protoinfo(val) = attr? {
6593 return Ok(val);
6594 }
6595 }
6596 Err(ErrorContext::new_missing(
6597 "OpGetDumpReply",
6598 "Protoinfo",
6599 self.orig_loc,
6600 self.buf.as_ptr() as usize,
6601 ))
6602 }
6603 pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
6604 let mut iter = self.clone();
6605 iter.pos = 0;
6606 for attr in iter {
6607 if let OpGetDumpReply::Help(val) = attr? {
6608 return Ok(val);
6609 }
6610 }
6611 Err(ErrorContext::new_missing(
6612 "OpGetDumpReply",
6613 "Help",
6614 self.orig_loc,
6615 self.buf.as_ptr() as usize,
6616 ))
6617 }
6618 pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
6619 let mut iter = self.clone();
6620 iter.pos = 0;
6621 for attr in iter {
6622 if let OpGetDumpReply::NatSrc(val) = attr? {
6623 return Ok(val);
6624 }
6625 }
6626 Err(ErrorContext::new_missing(
6627 "OpGetDumpReply",
6628 "NatSrc",
6629 self.orig_loc,
6630 self.buf.as_ptr() as usize,
6631 ))
6632 }
6633 pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
6634 let mut iter = self.clone();
6635 iter.pos = 0;
6636 for attr in iter {
6637 if let OpGetDumpReply::Timeout(val) = attr? {
6638 return Ok(val);
6639 }
6640 }
6641 Err(ErrorContext::new_missing(
6642 "OpGetDumpReply",
6643 "Timeout",
6644 self.orig_loc,
6645 self.buf.as_ptr() as usize,
6646 ))
6647 }
6648 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
6649 let mut iter = self.clone();
6650 iter.pos = 0;
6651 for attr in iter {
6652 if let OpGetDumpReply::Mark(val) = attr? {
6653 return Ok(val);
6654 }
6655 }
6656 Err(ErrorContext::new_missing(
6657 "OpGetDumpReply",
6658 "Mark",
6659 self.orig_loc,
6660 self.buf.as_ptr() as usize,
6661 ))
6662 }
6663 pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
6664 let mut iter = self.clone();
6665 iter.pos = 0;
6666 for attr in iter {
6667 if let OpGetDumpReply::CountersOrig(val) = attr? {
6668 return Ok(val);
6669 }
6670 }
6671 Err(ErrorContext::new_missing(
6672 "OpGetDumpReply",
6673 "CountersOrig",
6674 self.orig_loc,
6675 self.buf.as_ptr() as usize,
6676 ))
6677 }
6678 pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
6679 let mut iter = self.clone();
6680 iter.pos = 0;
6681 for attr in iter {
6682 if let OpGetDumpReply::CountersReply(val) = attr? {
6683 return Ok(val);
6684 }
6685 }
6686 Err(ErrorContext::new_missing(
6687 "OpGetDumpReply",
6688 "CountersReply",
6689 self.orig_loc,
6690 self.buf.as_ptr() as usize,
6691 ))
6692 }
6693 pub fn get_use(&self) -> Result<u32, ErrorContext> {
6694 let mut iter = self.clone();
6695 iter.pos = 0;
6696 for attr in iter {
6697 if let OpGetDumpReply::Use(val) = attr? {
6698 return Ok(val);
6699 }
6700 }
6701 Err(ErrorContext::new_missing(
6702 "OpGetDumpReply",
6703 "Use",
6704 self.orig_loc,
6705 self.buf.as_ptr() as usize,
6706 ))
6707 }
6708 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6709 let mut iter = self.clone();
6710 iter.pos = 0;
6711 for attr in iter {
6712 if let OpGetDumpReply::Id(val) = attr? {
6713 return Ok(val);
6714 }
6715 }
6716 Err(ErrorContext::new_missing(
6717 "OpGetDumpReply",
6718 "Id",
6719 self.orig_loc,
6720 self.buf.as_ptr() as usize,
6721 ))
6722 }
6723 pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
6724 let mut iter = self.clone();
6725 iter.pos = 0;
6726 for attr in iter {
6727 if let OpGetDumpReply::NatDst(val) = attr? {
6728 return Ok(val);
6729 }
6730 }
6731 Err(ErrorContext::new_missing(
6732 "OpGetDumpReply",
6733 "NatDst",
6734 self.orig_loc,
6735 self.buf.as_ptr() as usize,
6736 ))
6737 }
6738 pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
6739 let mut iter = self.clone();
6740 iter.pos = 0;
6741 for attr in iter {
6742 if let OpGetDumpReply::TupleMaster(val) = attr? {
6743 return Ok(val);
6744 }
6745 }
6746 Err(ErrorContext::new_missing(
6747 "OpGetDumpReply",
6748 "TupleMaster",
6749 self.orig_loc,
6750 self.buf.as_ptr() as usize,
6751 ))
6752 }
6753 pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
6754 let mut iter = self.clone();
6755 iter.pos = 0;
6756 for attr in iter {
6757 if let OpGetDumpReply::SeqAdjOrig(val) = attr? {
6758 return Ok(val);
6759 }
6760 }
6761 Err(ErrorContext::new_missing(
6762 "OpGetDumpReply",
6763 "SeqAdjOrig",
6764 self.orig_loc,
6765 self.buf.as_ptr() as usize,
6766 ))
6767 }
6768 pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
6769 let mut iter = self.clone();
6770 iter.pos = 0;
6771 for attr in iter {
6772 if let OpGetDumpReply::SeqAdjReply(val) = attr? {
6773 return Ok(val);
6774 }
6775 }
6776 Err(ErrorContext::new_missing(
6777 "OpGetDumpReply",
6778 "SeqAdjReply",
6779 self.orig_loc,
6780 self.buf.as_ptr() as usize,
6781 ))
6782 }
6783 #[doc = "conntrack zone id"]
6784 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
6785 let mut iter = self.clone();
6786 iter.pos = 0;
6787 for attr in iter {
6788 if let OpGetDumpReply::Zone(val) = attr? {
6789 return Ok(val);
6790 }
6791 }
6792 Err(ErrorContext::new_missing(
6793 "OpGetDumpReply",
6794 "Zone",
6795 self.orig_loc,
6796 self.buf.as_ptr() as usize,
6797 ))
6798 }
6799 pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
6800 let mut iter = self.clone();
6801 iter.pos = 0;
6802 for attr in iter {
6803 if let OpGetDumpReply::Secctx(val) = attr? {
6804 return Ok(val);
6805 }
6806 }
6807 Err(ErrorContext::new_missing(
6808 "OpGetDumpReply",
6809 "Secctx",
6810 self.orig_loc,
6811 self.buf.as_ptr() as usize,
6812 ))
6813 }
6814 pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
6815 let mut iter = self.clone();
6816 iter.pos = 0;
6817 for attr in iter {
6818 if let OpGetDumpReply::Labels(val) = attr? {
6819 return Ok(val);
6820 }
6821 }
6822 Err(ErrorContext::new_missing(
6823 "OpGetDumpReply",
6824 "Labels",
6825 self.orig_loc,
6826 self.buf.as_ptr() as usize,
6827 ))
6828 }
6829 pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
6830 let mut iter = self.clone();
6831 iter.pos = 0;
6832 for attr in iter {
6833 if let OpGetDumpReply::Synproxy(val) = attr? {
6834 return Ok(val);
6835 }
6836 }
6837 Err(ErrorContext::new_missing(
6838 "OpGetDumpReply",
6839 "Synproxy",
6840 self.orig_loc,
6841 self.buf.as_ptr() as usize,
6842 ))
6843 }
6844}
6845impl OpGetDumpReply<'_> {
6846 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDumpReply<'a>) {
6847 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
6848 (
6849 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
6850 IterableOpGetDumpReply::with_loc(attrs, buf.as_ptr() as usize),
6851 )
6852 }
6853 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6854 ConntrackAttrs::attr_from_type(r#type)
6855 }
6856}
6857#[derive(Clone, Copy, Default)]
6858pub struct IterableOpGetDumpReply<'a> {
6859 buf: &'a [u8],
6860 pos: usize,
6861 orig_loc: usize,
6862}
6863impl<'a> IterableOpGetDumpReply<'a> {
6864 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6865 Self {
6866 buf,
6867 pos: 0,
6868 orig_loc,
6869 }
6870 }
6871 pub fn get_buf(&self) -> &'a [u8] {
6872 self.buf
6873 }
6874}
6875impl<'a> Iterator for IterableOpGetDumpReply<'a> {
6876 type Item = Result<OpGetDumpReply<'a>, ErrorContext>;
6877 fn next(&mut self) -> Option<Self::Item> {
6878 let pos = self.pos;
6879 let mut r#type;
6880 loop {
6881 r#type = None;
6882 if self.buf.len() == self.pos {
6883 return None;
6884 }
6885 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6886 break;
6887 };
6888 r#type = Some(header.r#type);
6889 let res = match header.r#type {
6890 1u16 => OpGetDumpReply::TupleOrig({
6891 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6892 let Some(val) = res else { break };
6893 val
6894 }),
6895 2u16 => OpGetDumpReply::TupleReply({
6896 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6897 let Some(val) = res else { break };
6898 val
6899 }),
6900 3u16 => OpGetDumpReply::Status({
6901 let res = parse_be_u32(next);
6902 let Some(val) = res else { break };
6903 val
6904 }),
6905 4u16 => OpGetDumpReply::Protoinfo({
6906 let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
6907 let Some(val) = res else { break };
6908 val
6909 }),
6910 5u16 => OpGetDumpReply::Help({
6911 let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
6912 let Some(val) = res else { break };
6913 val
6914 }),
6915 6u16 => OpGetDumpReply::NatSrc({
6916 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
6917 let Some(val) = res else { break };
6918 val
6919 }),
6920 7u16 => OpGetDumpReply::Timeout({
6921 let res = parse_be_u32(next);
6922 let Some(val) = res else { break };
6923 val
6924 }),
6925 8u16 => OpGetDumpReply::Mark({
6926 let res = parse_be_u32(next);
6927 let Some(val) = res else { break };
6928 val
6929 }),
6930 9u16 => OpGetDumpReply::CountersOrig({
6931 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
6932 let Some(val) = res else { break };
6933 val
6934 }),
6935 10u16 => OpGetDumpReply::CountersReply({
6936 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
6937 let Some(val) = res else { break };
6938 val
6939 }),
6940 11u16 => OpGetDumpReply::Use({
6941 let res = parse_be_u32(next);
6942 let Some(val) = res else { break };
6943 val
6944 }),
6945 12u16 => OpGetDumpReply::Id({
6946 let res = parse_be_u32(next);
6947 let Some(val) = res else { break };
6948 val
6949 }),
6950 13u16 => OpGetDumpReply::NatDst({
6951 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
6952 let Some(val) = res else { break };
6953 val
6954 }),
6955 14u16 => OpGetDumpReply::TupleMaster({
6956 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
6957 let Some(val) = res else { break };
6958 val
6959 }),
6960 15u16 => OpGetDumpReply::SeqAdjOrig({
6961 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
6962 let Some(val) = res else { break };
6963 val
6964 }),
6965 16u16 => OpGetDumpReply::SeqAdjReply({
6966 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
6967 let Some(val) = res else { break };
6968 val
6969 }),
6970 18u16 => OpGetDumpReply::Zone({
6971 let res = parse_be_u16(next);
6972 let Some(val) = res else { break };
6973 val
6974 }),
6975 19u16 => OpGetDumpReply::Secctx({
6976 let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
6977 let Some(val) = res else { break };
6978 val
6979 }),
6980 22u16 => OpGetDumpReply::Labels({
6981 let res = Some(next);
6982 let Some(val) = res else { break };
6983 val
6984 }),
6985 24u16 => OpGetDumpReply::Synproxy({
6986 let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
6987 let Some(val) = res else { break };
6988 val
6989 }),
6990 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6991 n => continue,
6992 };
6993 return Some(Ok(res));
6994 }
6995 Some(Err(ErrorContext::new(
6996 "OpGetDumpReply",
6997 r#type.and_then(|t| OpGetDumpReply::attr_from_type(t)),
6998 self.orig_loc,
6999 self.buf.as_ptr().wrapping_add(pos) as usize,
7000 )))
7001 }
7002}
7003impl<'a> std::fmt::Debug for IterableOpGetDumpReply<'_> {
7004 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7005 let mut fmt = f.debug_struct("OpGetDumpReply");
7006 for attr in self.clone() {
7007 let attr = match attr {
7008 Ok(a) => a,
7009 Err(err) => {
7010 fmt.finish()?;
7011 f.write_str("Err(")?;
7012 err.fmt(f)?;
7013 return f.write_str(")");
7014 }
7015 };
7016 match attr {
7017 OpGetDumpReply::TupleOrig(val) => fmt.field("TupleOrig", &val),
7018 OpGetDumpReply::TupleReply(val) => fmt.field("TupleReply", &val),
7019 OpGetDumpReply::Status(val) => {
7020 fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
7021 }
7022 OpGetDumpReply::Protoinfo(val) => fmt.field("Protoinfo", &val),
7023 OpGetDumpReply::Help(val) => fmt.field("Help", &val),
7024 OpGetDumpReply::NatSrc(val) => fmt.field("NatSrc", &val),
7025 OpGetDumpReply::Timeout(val) => fmt.field("Timeout", &val),
7026 OpGetDumpReply::Mark(val) => fmt.field("Mark", &val),
7027 OpGetDumpReply::CountersOrig(val) => fmt.field("CountersOrig", &val),
7028 OpGetDumpReply::CountersReply(val) => fmt.field("CountersReply", &val),
7029 OpGetDumpReply::Use(val) => fmt.field("Use", &val),
7030 OpGetDumpReply::Id(val) => fmt.field("Id", &val),
7031 OpGetDumpReply::NatDst(val) => fmt.field("NatDst", &val),
7032 OpGetDumpReply::TupleMaster(val) => fmt.field("TupleMaster", &val),
7033 OpGetDumpReply::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
7034 OpGetDumpReply::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
7035 OpGetDumpReply::Zone(val) => fmt.field("Zone", &val),
7036 OpGetDumpReply::Secctx(val) => fmt.field("Secctx", &val),
7037 OpGetDumpReply::Labels(val) => fmt.field("Labels", &val),
7038 OpGetDumpReply::Synproxy(val) => fmt.field("Synproxy", &val),
7039 };
7040 }
7041 fmt.finish()
7042 }
7043}
7044impl IterableOpGetDumpReply<'_> {
7045 pub fn lookup_attr(
7046 &self,
7047 offset: usize,
7048 missing_type: Option<u16>,
7049 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7050 let mut stack = Vec::new();
7051 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7052 if cur == offset + PushNfgenmsg::len() {
7053 stack.push(("OpGetDumpReply", offset));
7054 return (
7055 stack,
7056 missing_type.and_then(|t| OpGetDumpReply::attr_from_type(t)),
7057 );
7058 }
7059 if cur > offset || cur + self.buf.len() < offset {
7060 return (stack, None);
7061 }
7062 let mut attrs = self.clone();
7063 let mut last_off = cur + attrs.pos;
7064 let mut missing = None;
7065 while let Some(attr) = attrs.next() {
7066 let Ok(attr) = attr else { break };
7067 match attr {
7068 OpGetDumpReply::TupleOrig(val) => {
7069 (stack, missing) = val.lookup_attr(offset, missing_type);
7070 if !stack.is_empty() {
7071 break;
7072 }
7073 }
7074 OpGetDumpReply::TupleReply(val) => {
7075 (stack, missing) = val.lookup_attr(offset, missing_type);
7076 if !stack.is_empty() {
7077 break;
7078 }
7079 }
7080 OpGetDumpReply::Status(val) => {
7081 if last_off == offset {
7082 stack.push(("Status", last_off));
7083 break;
7084 }
7085 }
7086 OpGetDumpReply::Protoinfo(val) => {
7087 (stack, missing) = val.lookup_attr(offset, missing_type);
7088 if !stack.is_empty() {
7089 break;
7090 }
7091 }
7092 OpGetDumpReply::Help(val) => {
7093 (stack, missing) = val.lookup_attr(offset, missing_type);
7094 if !stack.is_empty() {
7095 break;
7096 }
7097 }
7098 OpGetDumpReply::NatSrc(val) => {
7099 (stack, missing) = val.lookup_attr(offset, missing_type);
7100 if !stack.is_empty() {
7101 break;
7102 }
7103 }
7104 OpGetDumpReply::Timeout(val) => {
7105 if last_off == offset {
7106 stack.push(("Timeout", last_off));
7107 break;
7108 }
7109 }
7110 OpGetDumpReply::Mark(val) => {
7111 if last_off == offset {
7112 stack.push(("Mark", last_off));
7113 break;
7114 }
7115 }
7116 OpGetDumpReply::CountersOrig(val) => {
7117 (stack, missing) = val.lookup_attr(offset, missing_type);
7118 if !stack.is_empty() {
7119 break;
7120 }
7121 }
7122 OpGetDumpReply::CountersReply(val) => {
7123 (stack, missing) = val.lookup_attr(offset, missing_type);
7124 if !stack.is_empty() {
7125 break;
7126 }
7127 }
7128 OpGetDumpReply::Use(val) => {
7129 if last_off == offset {
7130 stack.push(("Use", last_off));
7131 break;
7132 }
7133 }
7134 OpGetDumpReply::Id(val) => {
7135 if last_off == offset {
7136 stack.push(("Id", last_off));
7137 break;
7138 }
7139 }
7140 OpGetDumpReply::NatDst(val) => {
7141 (stack, missing) = val.lookup_attr(offset, missing_type);
7142 if !stack.is_empty() {
7143 break;
7144 }
7145 }
7146 OpGetDumpReply::TupleMaster(val) => {
7147 (stack, missing) = val.lookup_attr(offset, missing_type);
7148 if !stack.is_empty() {
7149 break;
7150 }
7151 }
7152 OpGetDumpReply::SeqAdjOrig(val) => {
7153 (stack, missing) = val.lookup_attr(offset, missing_type);
7154 if !stack.is_empty() {
7155 break;
7156 }
7157 }
7158 OpGetDumpReply::SeqAdjReply(val) => {
7159 (stack, missing) = val.lookup_attr(offset, missing_type);
7160 if !stack.is_empty() {
7161 break;
7162 }
7163 }
7164 OpGetDumpReply::Zone(val) => {
7165 if last_off == offset {
7166 stack.push(("Zone", last_off));
7167 break;
7168 }
7169 }
7170 OpGetDumpReply::Secctx(val) => {
7171 (stack, missing) = val.lookup_attr(offset, missing_type);
7172 if !stack.is_empty() {
7173 break;
7174 }
7175 }
7176 OpGetDumpReply::Labels(val) => {
7177 if last_off == offset {
7178 stack.push(("Labels", last_off));
7179 break;
7180 }
7181 }
7182 OpGetDumpReply::Synproxy(val) => {
7183 (stack, missing) = val.lookup_attr(offset, missing_type);
7184 if !stack.is_empty() {
7185 break;
7186 }
7187 }
7188 _ => {}
7189 };
7190 last_off = cur + attrs.pos;
7191 }
7192 if !stack.is_empty() {
7193 stack.push(("OpGetDumpReply", cur));
7194 }
7195 (stack, missing)
7196 }
7197}
7198#[derive(Debug)]
7199pub struct RequestOpGetDumpRequest<'r> {
7200 request: Request<'r>,
7201}
7202impl<'r> RequestOpGetDumpRequest<'r> {
7203 pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
7204 PushOpGetDumpRequest::write_header(&mut request.buf_mut(), header);
7205 Self {
7206 request: request.set_dump(),
7207 }
7208 }
7209 pub fn encode(&mut self) -> PushOpGetDumpRequest<&mut Vec<u8>> {
7210 PushOpGetDumpRequest::new_without_header(self.request.buf_mut())
7211 }
7212 pub fn into_encoder(self) -> PushOpGetDumpRequest<RequestBuf<'r>> {
7213 PushOpGetDumpRequest::new_without_header(self.request.buf)
7214 }
7215 pub fn decode_request<'buf>(buf: &'buf [u8]) -> (PushNfgenmsg, IterableOpGetDumpRequest<'buf>) {
7216 OpGetDumpRequest::new(buf)
7217 }
7218}
7219impl NetlinkRequest for RequestOpGetDumpRequest<'_> {
7220 fn protocol(&self) -> Protocol {
7221 Protocol::Raw {
7222 protonum: 12u16,
7223 request_type: 257u16,
7224 }
7225 }
7226 fn flags(&self) -> u16 {
7227 self.request.flags
7228 }
7229 fn payload(&self) -> &[u8] {
7230 self.request.buf()
7231 }
7232 type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetDumpReply<'buf>);
7233 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7234 OpGetDumpReply::new(buf)
7235 }
7236 fn lookup(
7237 buf: &[u8],
7238 offset: usize,
7239 missing_type: Option<u16>,
7240 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7241 OpGetDumpRequest::new(buf)
7242 .1
7243 .lookup_attr(offset, missing_type)
7244 }
7245}
7246#[doc = "get / dump entries"]
7247pub struct PushOpGetDoRequest<Prev: Rec> {
7248 pub(crate) prev: Option<Prev>,
7249 pub(crate) header_offset: Option<usize>,
7250}
7251impl<Prev: Rec> Rec for PushOpGetDoRequest<Prev> {
7252 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7253 self.prev.as_mut().unwrap().as_rec_mut()
7254 }
7255 fn as_rec(&self) -> &Vec<u8> {
7256 self.prev.as_ref().unwrap().as_rec()
7257 }
7258}
7259impl<Prev: Rec> PushOpGetDoRequest<Prev> {
7260 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
7261 Self::write_header(&mut prev, header);
7262 Self::new_without_header(prev)
7263 }
7264 fn new_without_header(prev: Prev) -> Self {
7265 Self {
7266 prev: Some(prev),
7267 header_offset: None,
7268 }
7269 }
7270 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
7271 prev.as_rec_mut().extend(header.as_slice());
7272 }
7273 pub fn end_nested(mut self) -> Prev {
7274 let mut prev = self.prev.take().unwrap();
7275 if let Some(header_offset) = &self.header_offset {
7276 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7277 }
7278 prev
7279 }
7280 #[doc = "conntrack l3+l4 protocol information, original direction"]
7281 pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
7282 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7283 PushTupleAttrs {
7284 prev: Some(self),
7285 header_offset: Some(header_offset),
7286 }
7287 }
7288 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7289 pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
7290 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
7291 PushTupleAttrs {
7292 prev: Some(self),
7293 header_offset: Some(header_offset),
7294 }
7295 }
7296 #[doc = "conntrack zone id"]
7297 pub fn push_zone(mut self, value: u16) -> Self {
7298 push_header(self.as_rec_mut(), 18u16, 2 as u16);
7299 self.as_rec_mut().extend(value.to_be_bytes());
7300 self
7301 }
7302}
7303impl<Prev: Rec> Drop for PushOpGetDoRequest<Prev> {
7304 fn drop(&mut self) {
7305 if let Some(prev) = &mut self.prev {
7306 if let Some(header_offset) = &self.header_offset {
7307 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7308 }
7309 }
7310 }
7311}
7312#[doc = "get / dump entries"]
7313#[derive(Clone)]
7314pub enum OpGetDoRequest<'a> {
7315 #[doc = "conntrack l3+l4 protocol information, original direction"]
7316 TupleOrig(IterableTupleAttrs<'a>),
7317 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7318 TupleReply(IterableTupleAttrs<'a>),
7319 #[doc = "conntrack zone id"]
7320 Zone(u16),
7321}
7322impl<'a> IterableOpGetDoRequest<'a> {
7323 #[doc = "conntrack l3+l4 protocol information, original direction"]
7324 pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7325 let mut iter = self.clone();
7326 iter.pos = 0;
7327 for attr in iter {
7328 if let OpGetDoRequest::TupleOrig(val) = attr? {
7329 return Ok(val);
7330 }
7331 }
7332 Err(ErrorContext::new_missing(
7333 "OpGetDoRequest",
7334 "TupleOrig",
7335 self.orig_loc,
7336 self.buf.as_ptr() as usize,
7337 ))
7338 }
7339 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7340 pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7341 let mut iter = self.clone();
7342 iter.pos = 0;
7343 for attr in iter {
7344 if let OpGetDoRequest::TupleReply(val) = attr? {
7345 return Ok(val);
7346 }
7347 }
7348 Err(ErrorContext::new_missing(
7349 "OpGetDoRequest",
7350 "TupleReply",
7351 self.orig_loc,
7352 self.buf.as_ptr() as usize,
7353 ))
7354 }
7355 #[doc = "conntrack zone id"]
7356 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
7357 let mut iter = self.clone();
7358 iter.pos = 0;
7359 for attr in iter {
7360 if let OpGetDoRequest::Zone(val) = attr? {
7361 return Ok(val);
7362 }
7363 }
7364 Err(ErrorContext::new_missing(
7365 "OpGetDoRequest",
7366 "Zone",
7367 self.orig_loc,
7368 self.buf.as_ptr() as usize,
7369 ))
7370 }
7371}
7372impl OpGetDoRequest<'_> {
7373 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDoRequest<'a>) {
7374 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
7375 (
7376 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
7377 IterableOpGetDoRequest::with_loc(attrs, buf.as_ptr() as usize),
7378 )
7379 }
7380 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7381 ConntrackAttrs::attr_from_type(r#type)
7382 }
7383}
7384#[derive(Clone, Copy, Default)]
7385pub struct IterableOpGetDoRequest<'a> {
7386 buf: &'a [u8],
7387 pos: usize,
7388 orig_loc: usize,
7389}
7390impl<'a> IterableOpGetDoRequest<'a> {
7391 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7392 Self {
7393 buf,
7394 pos: 0,
7395 orig_loc,
7396 }
7397 }
7398 pub fn get_buf(&self) -> &'a [u8] {
7399 self.buf
7400 }
7401}
7402impl<'a> Iterator for IterableOpGetDoRequest<'a> {
7403 type Item = Result<OpGetDoRequest<'a>, ErrorContext>;
7404 fn next(&mut self) -> Option<Self::Item> {
7405 let pos = self.pos;
7406 let mut r#type;
7407 loop {
7408 r#type = None;
7409 if self.buf.len() == self.pos {
7410 return None;
7411 }
7412 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7413 break;
7414 };
7415 r#type = Some(header.r#type);
7416 let res = match header.r#type {
7417 1u16 => OpGetDoRequest::TupleOrig({
7418 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
7419 let Some(val) = res else { break };
7420 val
7421 }),
7422 2u16 => OpGetDoRequest::TupleReply({
7423 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
7424 let Some(val) = res else { break };
7425 val
7426 }),
7427 18u16 => OpGetDoRequest::Zone({
7428 let res = parse_be_u16(next);
7429 let Some(val) = res else { break };
7430 val
7431 }),
7432 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7433 n => continue,
7434 };
7435 return Some(Ok(res));
7436 }
7437 Some(Err(ErrorContext::new(
7438 "OpGetDoRequest",
7439 r#type.and_then(|t| OpGetDoRequest::attr_from_type(t)),
7440 self.orig_loc,
7441 self.buf.as_ptr().wrapping_add(pos) as usize,
7442 )))
7443 }
7444}
7445impl<'a> std::fmt::Debug for IterableOpGetDoRequest<'_> {
7446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7447 let mut fmt = f.debug_struct("OpGetDoRequest");
7448 for attr in self.clone() {
7449 let attr = match attr {
7450 Ok(a) => a,
7451 Err(err) => {
7452 fmt.finish()?;
7453 f.write_str("Err(")?;
7454 err.fmt(f)?;
7455 return f.write_str(")");
7456 }
7457 };
7458 match attr {
7459 OpGetDoRequest::TupleOrig(val) => fmt.field("TupleOrig", &val),
7460 OpGetDoRequest::TupleReply(val) => fmt.field("TupleReply", &val),
7461 OpGetDoRequest::Zone(val) => fmt.field("Zone", &val),
7462 };
7463 }
7464 fmt.finish()
7465 }
7466}
7467impl IterableOpGetDoRequest<'_> {
7468 pub fn lookup_attr(
7469 &self,
7470 offset: usize,
7471 missing_type: Option<u16>,
7472 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7473 let mut stack = Vec::new();
7474 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7475 if cur == offset + PushNfgenmsg::len() {
7476 stack.push(("OpGetDoRequest", offset));
7477 return (
7478 stack,
7479 missing_type.and_then(|t| OpGetDoRequest::attr_from_type(t)),
7480 );
7481 }
7482 if cur > offset || cur + self.buf.len() < offset {
7483 return (stack, None);
7484 }
7485 let mut attrs = self.clone();
7486 let mut last_off = cur + attrs.pos;
7487 let mut missing = None;
7488 while let Some(attr) = attrs.next() {
7489 let Ok(attr) = attr else { break };
7490 match attr {
7491 OpGetDoRequest::TupleOrig(val) => {
7492 (stack, missing) = val.lookup_attr(offset, missing_type);
7493 if !stack.is_empty() {
7494 break;
7495 }
7496 }
7497 OpGetDoRequest::TupleReply(val) => {
7498 (stack, missing) = val.lookup_attr(offset, missing_type);
7499 if !stack.is_empty() {
7500 break;
7501 }
7502 }
7503 OpGetDoRequest::Zone(val) => {
7504 if last_off == offset {
7505 stack.push(("Zone", last_off));
7506 break;
7507 }
7508 }
7509 _ => {}
7510 };
7511 last_off = cur + attrs.pos;
7512 }
7513 if !stack.is_empty() {
7514 stack.push(("OpGetDoRequest", cur));
7515 }
7516 (stack, missing)
7517 }
7518}
7519#[doc = "get / dump entries"]
7520pub struct PushOpGetDoReply<Prev: Rec> {
7521 pub(crate) prev: Option<Prev>,
7522 pub(crate) header_offset: Option<usize>,
7523}
7524impl<Prev: Rec> Rec for PushOpGetDoReply<Prev> {
7525 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7526 self.prev.as_mut().unwrap().as_rec_mut()
7527 }
7528 fn as_rec(&self) -> &Vec<u8> {
7529 self.prev.as_ref().unwrap().as_rec()
7530 }
7531}
7532impl<Prev: Rec> PushOpGetDoReply<Prev> {
7533 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
7534 Self::write_header(&mut prev, header);
7535 Self::new_without_header(prev)
7536 }
7537 fn new_without_header(prev: Prev) -> Self {
7538 Self {
7539 prev: Some(prev),
7540 header_offset: None,
7541 }
7542 }
7543 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
7544 prev.as_rec_mut().extend(header.as_slice());
7545 }
7546 pub fn end_nested(mut self) -> Prev {
7547 let mut prev = self.prev.take().unwrap();
7548 if let Some(header_offset) = &self.header_offset {
7549 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7550 }
7551 prev
7552 }
7553 #[doc = "conntrack l3+l4 protocol information, original direction"]
7554 pub fn nested_tuple_orig(mut self) -> PushTupleAttrs<Self> {
7555 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7556 PushTupleAttrs {
7557 prev: Some(self),
7558 header_offset: Some(header_offset),
7559 }
7560 }
7561 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7562 pub fn nested_tuple_reply(mut self) -> PushTupleAttrs<Self> {
7563 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
7564 PushTupleAttrs {
7565 prev: Some(self),
7566 header_offset: Some(header_offset),
7567 }
7568 }
7569 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7570 pub fn push_status(mut self, value: u32) -> Self {
7571 push_header(self.as_rec_mut(), 3u16, 4 as u16);
7572 self.as_rec_mut().extend(value.to_be_bytes());
7573 self
7574 }
7575 pub fn nested_protoinfo(mut self) -> PushProtoinfoAttrs<Self> {
7576 let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
7577 PushProtoinfoAttrs {
7578 prev: Some(self),
7579 header_offset: Some(header_offset),
7580 }
7581 }
7582 pub fn nested_help(mut self) -> PushHelpAttrs<Self> {
7583 let header_offset = push_nested_header(self.as_rec_mut(), 5u16);
7584 PushHelpAttrs {
7585 prev: Some(self),
7586 header_offset: Some(header_offset),
7587 }
7588 }
7589 pub fn nested_nat_src(mut self) -> PushNatAttrs<Self> {
7590 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
7591 PushNatAttrs {
7592 prev: Some(self),
7593 header_offset: Some(header_offset),
7594 }
7595 }
7596 pub fn push_timeout(mut self, value: u32) -> Self {
7597 push_header(self.as_rec_mut(), 7u16, 4 as u16);
7598 self.as_rec_mut().extend(value.to_be_bytes());
7599 self
7600 }
7601 pub fn push_mark(mut self, value: u32) -> Self {
7602 push_header(self.as_rec_mut(), 8u16, 4 as u16);
7603 self.as_rec_mut().extend(value.to_be_bytes());
7604 self
7605 }
7606 pub fn nested_counters_orig(mut self) -> PushCounterAttrs<Self> {
7607 let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
7608 PushCounterAttrs {
7609 prev: Some(self),
7610 header_offset: Some(header_offset),
7611 }
7612 }
7613 pub fn nested_counters_reply(mut self) -> PushCounterAttrs<Self> {
7614 let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
7615 PushCounterAttrs {
7616 prev: Some(self),
7617 header_offset: Some(header_offset),
7618 }
7619 }
7620 pub fn push_use(mut self, value: u32) -> Self {
7621 push_header(self.as_rec_mut(), 11u16, 4 as u16);
7622 self.as_rec_mut().extend(value.to_be_bytes());
7623 self
7624 }
7625 pub fn push_id(mut self, value: u32) -> Self {
7626 push_header(self.as_rec_mut(), 12u16, 4 as u16);
7627 self.as_rec_mut().extend(value.to_be_bytes());
7628 self
7629 }
7630 pub fn nested_nat_dst(mut self) -> PushNatAttrs<Self> {
7631 let header_offset = push_nested_header(self.as_rec_mut(), 13u16);
7632 PushNatAttrs {
7633 prev: Some(self),
7634 header_offset: Some(header_offset),
7635 }
7636 }
7637 pub fn nested_tuple_master(mut self) -> PushTupleAttrs<Self> {
7638 let header_offset = push_nested_header(self.as_rec_mut(), 14u16);
7639 PushTupleAttrs {
7640 prev: Some(self),
7641 header_offset: Some(header_offset),
7642 }
7643 }
7644 pub fn nested_seq_adj_orig(mut self) -> PushSeqadjAttrs<Self> {
7645 let header_offset = push_nested_header(self.as_rec_mut(), 15u16);
7646 PushSeqadjAttrs {
7647 prev: Some(self),
7648 header_offset: Some(header_offset),
7649 }
7650 }
7651 pub fn nested_seq_adj_reply(mut self) -> PushSeqadjAttrs<Self> {
7652 let header_offset = push_nested_header(self.as_rec_mut(), 16u16);
7653 PushSeqadjAttrs {
7654 prev: Some(self),
7655 header_offset: Some(header_offset),
7656 }
7657 }
7658 #[doc = "conntrack zone id"]
7659 pub fn push_zone(mut self, value: u16) -> Self {
7660 push_header(self.as_rec_mut(), 18u16, 2 as u16);
7661 self.as_rec_mut().extend(value.to_be_bytes());
7662 self
7663 }
7664 pub fn nested_secctx(mut self) -> PushSecctxAttrs<Self> {
7665 let header_offset = push_nested_header(self.as_rec_mut(), 19u16);
7666 PushSecctxAttrs {
7667 prev: Some(self),
7668 header_offset: Some(header_offset),
7669 }
7670 }
7671 pub fn push_labels(mut self, value: &[u8]) -> Self {
7672 push_header(self.as_rec_mut(), 22u16, value.len() as u16);
7673 self.as_rec_mut().extend(value);
7674 self
7675 }
7676 pub fn nested_synproxy(mut self) -> PushSynproxyAttrs<Self> {
7677 let header_offset = push_nested_header(self.as_rec_mut(), 24u16);
7678 PushSynproxyAttrs {
7679 prev: Some(self),
7680 header_offset: Some(header_offset),
7681 }
7682 }
7683}
7684impl<Prev: Rec> Drop for PushOpGetDoReply<Prev> {
7685 fn drop(&mut self) {
7686 if let Some(prev) = &mut self.prev {
7687 if let Some(header_offset) = &self.header_offset {
7688 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7689 }
7690 }
7691 }
7692}
7693#[doc = "get / dump entries"]
7694#[derive(Clone)]
7695pub enum OpGetDoReply<'a> {
7696 #[doc = "conntrack l3+l4 protocol information, original direction"]
7697 TupleOrig(IterableTupleAttrs<'a>),
7698 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7699 TupleReply(IterableTupleAttrs<'a>),
7700 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7701 Status(u32),
7702 Protoinfo(IterableProtoinfoAttrs<'a>),
7703 Help(IterableHelpAttrs<'a>),
7704 NatSrc(IterableNatAttrs<'a>),
7705 Timeout(u32),
7706 Mark(u32),
7707 CountersOrig(IterableCounterAttrs<'a>),
7708 CountersReply(IterableCounterAttrs<'a>),
7709 Use(u32),
7710 Id(u32),
7711 NatDst(IterableNatAttrs<'a>),
7712 TupleMaster(IterableTupleAttrs<'a>),
7713 SeqAdjOrig(IterableSeqadjAttrs<'a>),
7714 SeqAdjReply(IterableSeqadjAttrs<'a>),
7715 #[doc = "conntrack zone id"]
7716 Zone(u16),
7717 Secctx(IterableSecctxAttrs<'a>),
7718 Labels(&'a [u8]),
7719 Synproxy(IterableSynproxyAttrs<'a>),
7720}
7721impl<'a> IterableOpGetDoReply<'a> {
7722 #[doc = "conntrack l3+l4 protocol information, original direction"]
7723 pub fn get_tuple_orig(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7724 let mut iter = self.clone();
7725 iter.pos = 0;
7726 for attr in iter {
7727 if let OpGetDoReply::TupleOrig(val) = attr? {
7728 return Ok(val);
7729 }
7730 }
7731 Err(ErrorContext::new_missing(
7732 "OpGetDoReply",
7733 "TupleOrig",
7734 self.orig_loc,
7735 self.buf.as_ptr() as usize,
7736 ))
7737 }
7738 #[doc = "conntrack l3+l4 protocol information, reply direction"]
7739 pub fn get_tuple_reply(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7740 let mut iter = self.clone();
7741 iter.pos = 0;
7742 for attr in iter {
7743 if let OpGetDoReply::TupleReply(val) = attr? {
7744 return Ok(val);
7745 }
7746 }
7747 Err(ErrorContext::new_missing(
7748 "OpGetDoReply",
7749 "TupleReply",
7750 self.orig_loc,
7751 self.buf.as_ptr() as usize,
7752 ))
7753 }
7754 #[doc = "conntrack flag bits\nAssociated type: \"NfCtStatus\" (1 bit per enumeration)"]
7755 pub fn get_status(&self) -> Result<u32, ErrorContext> {
7756 let mut iter = self.clone();
7757 iter.pos = 0;
7758 for attr in iter {
7759 if let OpGetDoReply::Status(val) = attr? {
7760 return Ok(val);
7761 }
7762 }
7763 Err(ErrorContext::new_missing(
7764 "OpGetDoReply",
7765 "Status",
7766 self.orig_loc,
7767 self.buf.as_ptr() as usize,
7768 ))
7769 }
7770 pub fn get_protoinfo(&self) -> Result<IterableProtoinfoAttrs<'a>, ErrorContext> {
7771 let mut iter = self.clone();
7772 iter.pos = 0;
7773 for attr in iter {
7774 if let OpGetDoReply::Protoinfo(val) = attr? {
7775 return Ok(val);
7776 }
7777 }
7778 Err(ErrorContext::new_missing(
7779 "OpGetDoReply",
7780 "Protoinfo",
7781 self.orig_loc,
7782 self.buf.as_ptr() as usize,
7783 ))
7784 }
7785 pub fn get_help(&self) -> Result<IterableHelpAttrs<'a>, ErrorContext> {
7786 let mut iter = self.clone();
7787 iter.pos = 0;
7788 for attr in iter {
7789 if let OpGetDoReply::Help(val) = attr? {
7790 return Ok(val);
7791 }
7792 }
7793 Err(ErrorContext::new_missing(
7794 "OpGetDoReply",
7795 "Help",
7796 self.orig_loc,
7797 self.buf.as_ptr() as usize,
7798 ))
7799 }
7800 pub fn get_nat_src(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
7801 let mut iter = self.clone();
7802 iter.pos = 0;
7803 for attr in iter {
7804 if let OpGetDoReply::NatSrc(val) = attr? {
7805 return Ok(val);
7806 }
7807 }
7808 Err(ErrorContext::new_missing(
7809 "OpGetDoReply",
7810 "NatSrc",
7811 self.orig_loc,
7812 self.buf.as_ptr() as usize,
7813 ))
7814 }
7815 pub fn get_timeout(&self) -> Result<u32, ErrorContext> {
7816 let mut iter = self.clone();
7817 iter.pos = 0;
7818 for attr in iter {
7819 if let OpGetDoReply::Timeout(val) = attr? {
7820 return Ok(val);
7821 }
7822 }
7823 Err(ErrorContext::new_missing(
7824 "OpGetDoReply",
7825 "Timeout",
7826 self.orig_loc,
7827 self.buf.as_ptr() as usize,
7828 ))
7829 }
7830 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
7831 let mut iter = self.clone();
7832 iter.pos = 0;
7833 for attr in iter {
7834 if let OpGetDoReply::Mark(val) = attr? {
7835 return Ok(val);
7836 }
7837 }
7838 Err(ErrorContext::new_missing(
7839 "OpGetDoReply",
7840 "Mark",
7841 self.orig_loc,
7842 self.buf.as_ptr() as usize,
7843 ))
7844 }
7845 pub fn get_counters_orig(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
7846 let mut iter = self.clone();
7847 iter.pos = 0;
7848 for attr in iter {
7849 if let OpGetDoReply::CountersOrig(val) = attr? {
7850 return Ok(val);
7851 }
7852 }
7853 Err(ErrorContext::new_missing(
7854 "OpGetDoReply",
7855 "CountersOrig",
7856 self.orig_loc,
7857 self.buf.as_ptr() as usize,
7858 ))
7859 }
7860 pub fn get_counters_reply(&self) -> Result<IterableCounterAttrs<'a>, ErrorContext> {
7861 let mut iter = self.clone();
7862 iter.pos = 0;
7863 for attr in iter {
7864 if let OpGetDoReply::CountersReply(val) = attr? {
7865 return Ok(val);
7866 }
7867 }
7868 Err(ErrorContext::new_missing(
7869 "OpGetDoReply",
7870 "CountersReply",
7871 self.orig_loc,
7872 self.buf.as_ptr() as usize,
7873 ))
7874 }
7875 pub fn get_use(&self) -> Result<u32, ErrorContext> {
7876 let mut iter = self.clone();
7877 iter.pos = 0;
7878 for attr in iter {
7879 if let OpGetDoReply::Use(val) = attr? {
7880 return Ok(val);
7881 }
7882 }
7883 Err(ErrorContext::new_missing(
7884 "OpGetDoReply",
7885 "Use",
7886 self.orig_loc,
7887 self.buf.as_ptr() as usize,
7888 ))
7889 }
7890 pub fn get_id(&self) -> Result<u32, ErrorContext> {
7891 let mut iter = self.clone();
7892 iter.pos = 0;
7893 for attr in iter {
7894 if let OpGetDoReply::Id(val) = attr? {
7895 return Ok(val);
7896 }
7897 }
7898 Err(ErrorContext::new_missing(
7899 "OpGetDoReply",
7900 "Id",
7901 self.orig_loc,
7902 self.buf.as_ptr() as usize,
7903 ))
7904 }
7905 pub fn get_nat_dst(&self) -> Result<IterableNatAttrs<'a>, ErrorContext> {
7906 let mut iter = self.clone();
7907 iter.pos = 0;
7908 for attr in iter {
7909 if let OpGetDoReply::NatDst(val) = attr? {
7910 return Ok(val);
7911 }
7912 }
7913 Err(ErrorContext::new_missing(
7914 "OpGetDoReply",
7915 "NatDst",
7916 self.orig_loc,
7917 self.buf.as_ptr() as usize,
7918 ))
7919 }
7920 pub fn get_tuple_master(&self) -> Result<IterableTupleAttrs<'a>, ErrorContext> {
7921 let mut iter = self.clone();
7922 iter.pos = 0;
7923 for attr in iter {
7924 if let OpGetDoReply::TupleMaster(val) = attr? {
7925 return Ok(val);
7926 }
7927 }
7928 Err(ErrorContext::new_missing(
7929 "OpGetDoReply",
7930 "TupleMaster",
7931 self.orig_loc,
7932 self.buf.as_ptr() as usize,
7933 ))
7934 }
7935 pub fn get_seq_adj_orig(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
7936 let mut iter = self.clone();
7937 iter.pos = 0;
7938 for attr in iter {
7939 if let OpGetDoReply::SeqAdjOrig(val) = attr? {
7940 return Ok(val);
7941 }
7942 }
7943 Err(ErrorContext::new_missing(
7944 "OpGetDoReply",
7945 "SeqAdjOrig",
7946 self.orig_loc,
7947 self.buf.as_ptr() as usize,
7948 ))
7949 }
7950 pub fn get_seq_adj_reply(&self) -> Result<IterableSeqadjAttrs<'a>, ErrorContext> {
7951 let mut iter = self.clone();
7952 iter.pos = 0;
7953 for attr in iter {
7954 if let OpGetDoReply::SeqAdjReply(val) = attr? {
7955 return Ok(val);
7956 }
7957 }
7958 Err(ErrorContext::new_missing(
7959 "OpGetDoReply",
7960 "SeqAdjReply",
7961 self.orig_loc,
7962 self.buf.as_ptr() as usize,
7963 ))
7964 }
7965 #[doc = "conntrack zone id"]
7966 pub fn get_zone(&self) -> Result<u16, ErrorContext> {
7967 let mut iter = self.clone();
7968 iter.pos = 0;
7969 for attr in iter {
7970 if let OpGetDoReply::Zone(val) = attr? {
7971 return Ok(val);
7972 }
7973 }
7974 Err(ErrorContext::new_missing(
7975 "OpGetDoReply",
7976 "Zone",
7977 self.orig_loc,
7978 self.buf.as_ptr() as usize,
7979 ))
7980 }
7981 pub fn get_secctx(&self) -> Result<IterableSecctxAttrs<'a>, ErrorContext> {
7982 let mut iter = self.clone();
7983 iter.pos = 0;
7984 for attr in iter {
7985 if let OpGetDoReply::Secctx(val) = attr? {
7986 return Ok(val);
7987 }
7988 }
7989 Err(ErrorContext::new_missing(
7990 "OpGetDoReply",
7991 "Secctx",
7992 self.orig_loc,
7993 self.buf.as_ptr() as usize,
7994 ))
7995 }
7996 pub fn get_labels(&self) -> Result<&'a [u8], ErrorContext> {
7997 let mut iter = self.clone();
7998 iter.pos = 0;
7999 for attr in iter {
8000 if let OpGetDoReply::Labels(val) = attr? {
8001 return Ok(val);
8002 }
8003 }
8004 Err(ErrorContext::new_missing(
8005 "OpGetDoReply",
8006 "Labels",
8007 self.orig_loc,
8008 self.buf.as_ptr() as usize,
8009 ))
8010 }
8011 pub fn get_synproxy(&self) -> Result<IterableSynproxyAttrs<'a>, ErrorContext> {
8012 let mut iter = self.clone();
8013 iter.pos = 0;
8014 for attr in iter {
8015 if let OpGetDoReply::Synproxy(val) = attr? {
8016 return Ok(val);
8017 }
8018 }
8019 Err(ErrorContext::new_missing(
8020 "OpGetDoReply",
8021 "Synproxy",
8022 self.orig_loc,
8023 self.buf.as_ptr() as usize,
8024 ))
8025 }
8026}
8027impl OpGetDoReply<'_> {
8028 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetDoReply<'a>) {
8029 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8030 (
8031 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8032 IterableOpGetDoReply::with_loc(attrs, buf.as_ptr() as usize),
8033 )
8034 }
8035 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8036 ConntrackAttrs::attr_from_type(r#type)
8037 }
8038}
8039#[derive(Clone, Copy, Default)]
8040pub struct IterableOpGetDoReply<'a> {
8041 buf: &'a [u8],
8042 pos: usize,
8043 orig_loc: usize,
8044}
8045impl<'a> IterableOpGetDoReply<'a> {
8046 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8047 Self {
8048 buf,
8049 pos: 0,
8050 orig_loc,
8051 }
8052 }
8053 pub fn get_buf(&self) -> &'a [u8] {
8054 self.buf
8055 }
8056}
8057impl<'a> Iterator for IterableOpGetDoReply<'a> {
8058 type Item = Result<OpGetDoReply<'a>, ErrorContext>;
8059 fn next(&mut self) -> Option<Self::Item> {
8060 let pos = self.pos;
8061 let mut r#type;
8062 loop {
8063 r#type = None;
8064 if self.buf.len() == self.pos {
8065 return None;
8066 }
8067 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8068 break;
8069 };
8070 r#type = Some(header.r#type);
8071 let res = match header.r#type {
8072 1u16 => OpGetDoReply::TupleOrig({
8073 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8074 let Some(val) = res else { break };
8075 val
8076 }),
8077 2u16 => OpGetDoReply::TupleReply({
8078 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8079 let Some(val) = res else { break };
8080 val
8081 }),
8082 3u16 => OpGetDoReply::Status({
8083 let res = parse_be_u32(next);
8084 let Some(val) = res else { break };
8085 val
8086 }),
8087 4u16 => OpGetDoReply::Protoinfo({
8088 let res = Some(IterableProtoinfoAttrs::with_loc(next, self.orig_loc));
8089 let Some(val) = res else { break };
8090 val
8091 }),
8092 5u16 => OpGetDoReply::Help({
8093 let res = Some(IterableHelpAttrs::with_loc(next, self.orig_loc));
8094 let Some(val) = res else { break };
8095 val
8096 }),
8097 6u16 => OpGetDoReply::NatSrc({
8098 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
8099 let Some(val) = res else { break };
8100 val
8101 }),
8102 7u16 => OpGetDoReply::Timeout({
8103 let res = parse_be_u32(next);
8104 let Some(val) = res else { break };
8105 val
8106 }),
8107 8u16 => OpGetDoReply::Mark({
8108 let res = parse_be_u32(next);
8109 let Some(val) = res else { break };
8110 val
8111 }),
8112 9u16 => OpGetDoReply::CountersOrig({
8113 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
8114 let Some(val) = res else { break };
8115 val
8116 }),
8117 10u16 => OpGetDoReply::CountersReply({
8118 let res = Some(IterableCounterAttrs::with_loc(next, self.orig_loc));
8119 let Some(val) = res else { break };
8120 val
8121 }),
8122 11u16 => OpGetDoReply::Use({
8123 let res = parse_be_u32(next);
8124 let Some(val) = res else { break };
8125 val
8126 }),
8127 12u16 => OpGetDoReply::Id({
8128 let res = parse_be_u32(next);
8129 let Some(val) = res else { break };
8130 val
8131 }),
8132 13u16 => OpGetDoReply::NatDst({
8133 let res = Some(IterableNatAttrs::with_loc(next, self.orig_loc));
8134 let Some(val) = res else { break };
8135 val
8136 }),
8137 14u16 => OpGetDoReply::TupleMaster({
8138 let res = Some(IterableTupleAttrs::with_loc(next, self.orig_loc));
8139 let Some(val) = res else { break };
8140 val
8141 }),
8142 15u16 => OpGetDoReply::SeqAdjOrig({
8143 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
8144 let Some(val) = res else { break };
8145 val
8146 }),
8147 16u16 => OpGetDoReply::SeqAdjReply({
8148 let res = Some(IterableSeqadjAttrs::with_loc(next, self.orig_loc));
8149 let Some(val) = res else { break };
8150 val
8151 }),
8152 18u16 => OpGetDoReply::Zone({
8153 let res = parse_be_u16(next);
8154 let Some(val) = res else { break };
8155 val
8156 }),
8157 19u16 => OpGetDoReply::Secctx({
8158 let res = Some(IterableSecctxAttrs::with_loc(next, self.orig_loc));
8159 let Some(val) = res else { break };
8160 val
8161 }),
8162 22u16 => OpGetDoReply::Labels({
8163 let res = Some(next);
8164 let Some(val) = res else { break };
8165 val
8166 }),
8167 24u16 => OpGetDoReply::Synproxy({
8168 let res = Some(IterableSynproxyAttrs::with_loc(next, self.orig_loc));
8169 let Some(val) = res else { break };
8170 val
8171 }),
8172 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8173 n => continue,
8174 };
8175 return Some(Ok(res));
8176 }
8177 Some(Err(ErrorContext::new(
8178 "OpGetDoReply",
8179 r#type.and_then(|t| OpGetDoReply::attr_from_type(t)),
8180 self.orig_loc,
8181 self.buf.as_ptr().wrapping_add(pos) as usize,
8182 )))
8183 }
8184}
8185impl<'a> std::fmt::Debug for IterableOpGetDoReply<'_> {
8186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8187 let mut fmt = f.debug_struct("OpGetDoReply");
8188 for attr in self.clone() {
8189 let attr = match attr {
8190 Ok(a) => a,
8191 Err(err) => {
8192 fmt.finish()?;
8193 f.write_str("Err(")?;
8194 err.fmt(f)?;
8195 return f.write_str(")");
8196 }
8197 };
8198 match attr {
8199 OpGetDoReply::TupleOrig(val) => fmt.field("TupleOrig", &val),
8200 OpGetDoReply::TupleReply(val) => fmt.field("TupleReply", &val),
8201 OpGetDoReply::Status(val) => {
8202 fmt.field("Status", &FormatFlags(val.into(), NfCtStatus::from_value))
8203 }
8204 OpGetDoReply::Protoinfo(val) => fmt.field("Protoinfo", &val),
8205 OpGetDoReply::Help(val) => fmt.field("Help", &val),
8206 OpGetDoReply::NatSrc(val) => fmt.field("NatSrc", &val),
8207 OpGetDoReply::Timeout(val) => fmt.field("Timeout", &val),
8208 OpGetDoReply::Mark(val) => fmt.field("Mark", &val),
8209 OpGetDoReply::CountersOrig(val) => fmt.field("CountersOrig", &val),
8210 OpGetDoReply::CountersReply(val) => fmt.field("CountersReply", &val),
8211 OpGetDoReply::Use(val) => fmt.field("Use", &val),
8212 OpGetDoReply::Id(val) => fmt.field("Id", &val),
8213 OpGetDoReply::NatDst(val) => fmt.field("NatDst", &val),
8214 OpGetDoReply::TupleMaster(val) => fmt.field("TupleMaster", &val),
8215 OpGetDoReply::SeqAdjOrig(val) => fmt.field("SeqAdjOrig", &val),
8216 OpGetDoReply::SeqAdjReply(val) => fmt.field("SeqAdjReply", &val),
8217 OpGetDoReply::Zone(val) => fmt.field("Zone", &val),
8218 OpGetDoReply::Secctx(val) => fmt.field("Secctx", &val),
8219 OpGetDoReply::Labels(val) => fmt.field("Labels", &val),
8220 OpGetDoReply::Synproxy(val) => fmt.field("Synproxy", &val),
8221 };
8222 }
8223 fmt.finish()
8224 }
8225}
8226impl IterableOpGetDoReply<'_> {
8227 pub fn lookup_attr(
8228 &self,
8229 offset: usize,
8230 missing_type: Option<u16>,
8231 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8232 let mut stack = Vec::new();
8233 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8234 if cur == offset + PushNfgenmsg::len() {
8235 stack.push(("OpGetDoReply", offset));
8236 return (
8237 stack,
8238 missing_type.and_then(|t| OpGetDoReply::attr_from_type(t)),
8239 );
8240 }
8241 if cur > offset || cur + self.buf.len() < offset {
8242 return (stack, None);
8243 }
8244 let mut attrs = self.clone();
8245 let mut last_off = cur + attrs.pos;
8246 let mut missing = None;
8247 while let Some(attr) = attrs.next() {
8248 let Ok(attr) = attr else { break };
8249 match attr {
8250 OpGetDoReply::TupleOrig(val) => {
8251 (stack, missing) = val.lookup_attr(offset, missing_type);
8252 if !stack.is_empty() {
8253 break;
8254 }
8255 }
8256 OpGetDoReply::TupleReply(val) => {
8257 (stack, missing) = val.lookup_attr(offset, missing_type);
8258 if !stack.is_empty() {
8259 break;
8260 }
8261 }
8262 OpGetDoReply::Status(val) => {
8263 if last_off == offset {
8264 stack.push(("Status", last_off));
8265 break;
8266 }
8267 }
8268 OpGetDoReply::Protoinfo(val) => {
8269 (stack, missing) = val.lookup_attr(offset, missing_type);
8270 if !stack.is_empty() {
8271 break;
8272 }
8273 }
8274 OpGetDoReply::Help(val) => {
8275 (stack, missing) = val.lookup_attr(offset, missing_type);
8276 if !stack.is_empty() {
8277 break;
8278 }
8279 }
8280 OpGetDoReply::NatSrc(val) => {
8281 (stack, missing) = val.lookup_attr(offset, missing_type);
8282 if !stack.is_empty() {
8283 break;
8284 }
8285 }
8286 OpGetDoReply::Timeout(val) => {
8287 if last_off == offset {
8288 stack.push(("Timeout", last_off));
8289 break;
8290 }
8291 }
8292 OpGetDoReply::Mark(val) => {
8293 if last_off == offset {
8294 stack.push(("Mark", last_off));
8295 break;
8296 }
8297 }
8298 OpGetDoReply::CountersOrig(val) => {
8299 (stack, missing) = val.lookup_attr(offset, missing_type);
8300 if !stack.is_empty() {
8301 break;
8302 }
8303 }
8304 OpGetDoReply::CountersReply(val) => {
8305 (stack, missing) = val.lookup_attr(offset, missing_type);
8306 if !stack.is_empty() {
8307 break;
8308 }
8309 }
8310 OpGetDoReply::Use(val) => {
8311 if last_off == offset {
8312 stack.push(("Use", last_off));
8313 break;
8314 }
8315 }
8316 OpGetDoReply::Id(val) => {
8317 if last_off == offset {
8318 stack.push(("Id", last_off));
8319 break;
8320 }
8321 }
8322 OpGetDoReply::NatDst(val) => {
8323 (stack, missing) = val.lookup_attr(offset, missing_type);
8324 if !stack.is_empty() {
8325 break;
8326 }
8327 }
8328 OpGetDoReply::TupleMaster(val) => {
8329 (stack, missing) = val.lookup_attr(offset, missing_type);
8330 if !stack.is_empty() {
8331 break;
8332 }
8333 }
8334 OpGetDoReply::SeqAdjOrig(val) => {
8335 (stack, missing) = val.lookup_attr(offset, missing_type);
8336 if !stack.is_empty() {
8337 break;
8338 }
8339 }
8340 OpGetDoReply::SeqAdjReply(val) => {
8341 (stack, missing) = val.lookup_attr(offset, missing_type);
8342 if !stack.is_empty() {
8343 break;
8344 }
8345 }
8346 OpGetDoReply::Zone(val) => {
8347 if last_off == offset {
8348 stack.push(("Zone", last_off));
8349 break;
8350 }
8351 }
8352 OpGetDoReply::Secctx(val) => {
8353 (stack, missing) = val.lookup_attr(offset, missing_type);
8354 if !stack.is_empty() {
8355 break;
8356 }
8357 }
8358 OpGetDoReply::Labels(val) => {
8359 if last_off == offset {
8360 stack.push(("Labels", last_off));
8361 break;
8362 }
8363 }
8364 OpGetDoReply::Synproxy(val) => {
8365 (stack, missing) = val.lookup_attr(offset, missing_type);
8366 if !stack.is_empty() {
8367 break;
8368 }
8369 }
8370 _ => {}
8371 };
8372 last_off = cur + attrs.pos;
8373 }
8374 if !stack.is_empty() {
8375 stack.push(("OpGetDoReply", cur));
8376 }
8377 (stack, missing)
8378 }
8379}
8380#[derive(Debug)]
8381pub struct RequestOpGetDoRequest<'r> {
8382 request: Request<'r>,
8383}
8384impl<'r> RequestOpGetDoRequest<'r> {
8385 pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
8386 PushOpGetDoRequest::write_header(&mut request.buf_mut(), header);
8387 Self { request: request }
8388 }
8389 pub fn encode(&mut self) -> PushOpGetDoRequest<&mut Vec<u8>> {
8390 PushOpGetDoRequest::new_without_header(self.request.buf_mut())
8391 }
8392 pub fn into_encoder(self) -> PushOpGetDoRequest<RequestBuf<'r>> {
8393 PushOpGetDoRequest::new_without_header(self.request.buf)
8394 }
8395 pub fn decode_request<'buf>(buf: &'buf [u8]) -> (PushNfgenmsg, IterableOpGetDoRequest<'buf>) {
8396 OpGetDoRequest::new(buf)
8397 }
8398}
8399impl NetlinkRequest for RequestOpGetDoRequest<'_> {
8400 fn protocol(&self) -> Protocol {
8401 Protocol::Raw {
8402 protonum: 12u16,
8403 request_type: 257u16,
8404 }
8405 }
8406 fn flags(&self) -> u16 {
8407 self.request.flags
8408 }
8409 fn payload(&self) -> &[u8] {
8410 self.request.buf()
8411 }
8412 type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetDoReply<'buf>);
8413 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8414 OpGetDoReply::new(buf)
8415 }
8416 fn lookup(
8417 buf: &[u8],
8418 offset: usize,
8419 missing_type: Option<u16>,
8420 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8421 OpGetDoRequest::new(buf).1.lookup_attr(offset, missing_type)
8422 }
8423}
8424#[doc = "dump pcpu conntrack stats"]
8425pub struct PushOpGetStatsDumpRequest<Prev: Rec> {
8426 pub(crate) prev: Option<Prev>,
8427 pub(crate) header_offset: Option<usize>,
8428}
8429impl<Prev: Rec> Rec for PushOpGetStatsDumpRequest<Prev> {
8430 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8431 self.prev.as_mut().unwrap().as_rec_mut()
8432 }
8433 fn as_rec(&self) -> &Vec<u8> {
8434 self.prev.as_ref().unwrap().as_rec()
8435 }
8436}
8437impl<Prev: Rec> PushOpGetStatsDumpRequest<Prev> {
8438 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
8439 Self::write_header(&mut prev, header);
8440 Self::new_without_header(prev)
8441 }
8442 fn new_without_header(prev: Prev) -> Self {
8443 Self {
8444 prev: Some(prev),
8445 header_offset: None,
8446 }
8447 }
8448 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
8449 prev.as_rec_mut().extend(header.as_slice());
8450 }
8451 pub fn end_nested(mut self) -> Prev {
8452 let mut prev = self.prev.take().unwrap();
8453 if let Some(header_offset) = &self.header_offset {
8454 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8455 }
8456 prev
8457 }
8458}
8459impl<Prev: Rec> Drop for PushOpGetStatsDumpRequest<Prev> {
8460 fn drop(&mut self) {
8461 if let Some(prev) = &mut self.prev {
8462 if let Some(header_offset) = &self.header_offset {
8463 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8464 }
8465 }
8466 }
8467}
8468#[doc = "dump pcpu conntrack stats"]
8469#[derive(Clone)]
8470pub enum OpGetStatsDumpRequest {}
8471impl<'a> IterableOpGetStatsDumpRequest<'a> {}
8472impl OpGetStatsDumpRequest {
8473 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetStatsDumpRequest<'a>) {
8474 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8475 (
8476 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8477 IterableOpGetStatsDumpRequest::with_loc(attrs, buf.as_ptr() as usize),
8478 )
8479 }
8480 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8481 ConntrackStatsAttrs::attr_from_type(r#type)
8482 }
8483}
8484#[derive(Clone, Copy, Default)]
8485pub struct IterableOpGetStatsDumpRequest<'a> {
8486 buf: &'a [u8],
8487 pos: usize,
8488 orig_loc: usize,
8489}
8490impl<'a> IterableOpGetStatsDumpRequest<'a> {
8491 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8492 Self {
8493 buf,
8494 pos: 0,
8495 orig_loc,
8496 }
8497 }
8498 pub fn get_buf(&self) -> &'a [u8] {
8499 self.buf
8500 }
8501}
8502impl<'a> Iterator for IterableOpGetStatsDumpRequest<'a> {
8503 type Item = Result<OpGetStatsDumpRequest, ErrorContext>;
8504 fn next(&mut self) -> Option<Self::Item> {
8505 let pos = self.pos;
8506 let mut r#type;
8507 loop {
8508 r#type = None;
8509 if self.buf.len() == self.pos {
8510 return None;
8511 }
8512 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8513 break;
8514 };
8515 r#type = Some(header.r#type);
8516 let res = match header.r#type {
8517 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8518 n => continue,
8519 };
8520 return Some(Ok(res));
8521 }
8522 Some(Err(ErrorContext::new(
8523 "OpGetStatsDumpRequest",
8524 r#type.and_then(|t| OpGetStatsDumpRequest::attr_from_type(t)),
8525 self.orig_loc,
8526 self.buf.as_ptr().wrapping_add(pos) as usize,
8527 )))
8528 }
8529}
8530impl std::fmt::Debug for IterableOpGetStatsDumpRequest<'_> {
8531 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8532 let mut fmt = f.debug_struct("OpGetStatsDumpRequest");
8533 for attr in self.clone() {
8534 let attr = match attr {
8535 Ok(a) => a,
8536 Err(err) => {
8537 fmt.finish()?;
8538 f.write_str("Err(")?;
8539 err.fmt(f)?;
8540 return f.write_str(")");
8541 }
8542 };
8543 match attr {};
8544 }
8545 fmt.finish()
8546 }
8547}
8548impl IterableOpGetStatsDumpRequest<'_> {
8549 pub fn lookup_attr(
8550 &self,
8551 offset: usize,
8552 missing_type: Option<u16>,
8553 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8554 let mut stack = Vec::new();
8555 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8556 if cur == offset + PushNfgenmsg::len() {
8557 stack.push(("OpGetStatsDumpRequest", offset));
8558 return (
8559 stack,
8560 missing_type.and_then(|t| OpGetStatsDumpRequest::attr_from_type(t)),
8561 );
8562 }
8563 (stack, None)
8564 }
8565}
8566#[doc = "dump pcpu conntrack stats"]
8567pub struct PushOpGetStatsDumpReply<Prev: Rec> {
8568 pub(crate) prev: Option<Prev>,
8569 pub(crate) header_offset: Option<usize>,
8570}
8571impl<Prev: Rec> Rec for PushOpGetStatsDumpReply<Prev> {
8572 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8573 self.prev.as_mut().unwrap().as_rec_mut()
8574 }
8575 fn as_rec(&self) -> &Vec<u8> {
8576 self.prev.as_ref().unwrap().as_rec()
8577 }
8578}
8579impl<Prev: Rec> PushOpGetStatsDumpReply<Prev> {
8580 pub fn new(mut prev: Prev, header: &PushNfgenmsg) -> Self {
8581 Self::write_header(&mut prev, header);
8582 Self::new_without_header(prev)
8583 }
8584 fn new_without_header(prev: Prev) -> Self {
8585 Self {
8586 prev: Some(prev),
8587 header_offset: None,
8588 }
8589 }
8590 fn write_header(prev: &mut Prev, header: &PushNfgenmsg) {
8591 prev.as_rec_mut().extend(header.as_slice());
8592 }
8593 pub fn end_nested(mut self) -> Prev {
8594 let mut prev = self.prev.take().unwrap();
8595 if let Some(header_offset) = &self.header_offset {
8596 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8597 }
8598 prev
8599 }
8600 #[doc = "obsolete"]
8601 pub fn push_searched(mut self, value: u32) -> Self {
8602 push_header(self.as_rec_mut(), 1u16, 4 as u16);
8603 self.as_rec_mut().extend(value.to_be_bytes());
8604 self
8605 }
8606 pub fn push_found(mut self, value: u32) -> Self {
8607 push_header(self.as_rec_mut(), 2u16, 4 as u16);
8608 self.as_rec_mut().extend(value.to_be_bytes());
8609 self
8610 }
8611 pub fn push_insert(mut self, value: u32) -> Self {
8612 push_header(self.as_rec_mut(), 8u16, 4 as u16);
8613 self.as_rec_mut().extend(value.to_be_bytes());
8614 self
8615 }
8616 pub fn push_insert_failed(mut self, value: u32) -> Self {
8617 push_header(self.as_rec_mut(), 9u16, 4 as u16);
8618 self.as_rec_mut().extend(value.to_be_bytes());
8619 self
8620 }
8621 pub fn push_drop(mut self, value: u32) -> Self {
8622 push_header(self.as_rec_mut(), 10u16, 4 as u16);
8623 self.as_rec_mut().extend(value.to_be_bytes());
8624 self
8625 }
8626 pub fn push_early_drop(mut self, value: u32) -> Self {
8627 push_header(self.as_rec_mut(), 11u16, 4 as u16);
8628 self.as_rec_mut().extend(value.to_be_bytes());
8629 self
8630 }
8631 pub fn push_error(mut self, value: u32) -> Self {
8632 push_header(self.as_rec_mut(), 12u16, 4 as u16);
8633 self.as_rec_mut().extend(value.to_be_bytes());
8634 self
8635 }
8636 pub fn push_search_restart(mut self, value: u32) -> Self {
8637 push_header(self.as_rec_mut(), 13u16, 4 as u16);
8638 self.as_rec_mut().extend(value.to_be_bytes());
8639 self
8640 }
8641 pub fn push_clash_resolve(mut self, value: u32) -> Self {
8642 push_header(self.as_rec_mut(), 14u16, 4 as u16);
8643 self.as_rec_mut().extend(value.to_be_bytes());
8644 self
8645 }
8646 pub fn push_chain_toolong(mut self, value: u32) -> Self {
8647 push_header(self.as_rec_mut(), 15u16, 4 as u16);
8648 self.as_rec_mut().extend(value.to_be_bytes());
8649 self
8650 }
8651}
8652impl<Prev: Rec> Drop for PushOpGetStatsDumpReply<Prev> {
8653 fn drop(&mut self) {
8654 if let Some(prev) = &mut self.prev {
8655 if let Some(header_offset) = &self.header_offset {
8656 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8657 }
8658 }
8659 }
8660}
8661#[doc = "dump pcpu conntrack stats"]
8662#[derive(Clone)]
8663pub enum OpGetStatsDumpReply {
8664 #[doc = "obsolete"]
8665 Searched(u32),
8666 Found(u32),
8667 Insert(u32),
8668 InsertFailed(u32),
8669 Drop(u32),
8670 EarlyDrop(u32),
8671 Error(u32),
8672 SearchRestart(u32),
8673 ClashResolve(u32),
8674 ChainToolong(u32),
8675}
8676impl<'a> IterableOpGetStatsDumpReply<'a> {
8677 #[doc = "obsolete"]
8678 pub fn get_searched(&self) -> Result<u32, ErrorContext> {
8679 let mut iter = self.clone();
8680 iter.pos = 0;
8681 for attr in iter {
8682 if let OpGetStatsDumpReply::Searched(val) = attr? {
8683 return Ok(val);
8684 }
8685 }
8686 Err(ErrorContext::new_missing(
8687 "OpGetStatsDumpReply",
8688 "Searched",
8689 self.orig_loc,
8690 self.buf.as_ptr() as usize,
8691 ))
8692 }
8693 pub fn get_found(&self) -> Result<u32, ErrorContext> {
8694 let mut iter = self.clone();
8695 iter.pos = 0;
8696 for attr in iter {
8697 if let OpGetStatsDumpReply::Found(val) = attr? {
8698 return Ok(val);
8699 }
8700 }
8701 Err(ErrorContext::new_missing(
8702 "OpGetStatsDumpReply",
8703 "Found",
8704 self.orig_loc,
8705 self.buf.as_ptr() as usize,
8706 ))
8707 }
8708 pub fn get_insert(&self) -> Result<u32, ErrorContext> {
8709 let mut iter = self.clone();
8710 iter.pos = 0;
8711 for attr in iter {
8712 if let OpGetStatsDumpReply::Insert(val) = attr? {
8713 return Ok(val);
8714 }
8715 }
8716 Err(ErrorContext::new_missing(
8717 "OpGetStatsDumpReply",
8718 "Insert",
8719 self.orig_loc,
8720 self.buf.as_ptr() as usize,
8721 ))
8722 }
8723 pub fn get_insert_failed(&self) -> Result<u32, ErrorContext> {
8724 let mut iter = self.clone();
8725 iter.pos = 0;
8726 for attr in iter {
8727 if let OpGetStatsDumpReply::InsertFailed(val) = attr? {
8728 return Ok(val);
8729 }
8730 }
8731 Err(ErrorContext::new_missing(
8732 "OpGetStatsDumpReply",
8733 "InsertFailed",
8734 self.orig_loc,
8735 self.buf.as_ptr() as usize,
8736 ))
8737 }
8738 pub fn get_drop(&self) -> Result<u32, ErrorContext> {
8739 let mut iter = self.clone();
8740 iter.pos = 0;
8741 for attr in iter {
8742 if let OpGetStatsDumpReply::Drop(val) = attr? {
8743 return Ok(val);
8744 }
8745 }
8746 Err(ErrorContext::new_missing(
8747 "OpGetStatsDumpReply",
8748 "Drop",
8749 self.orig_loc,
8750 self.buf.as_ptr() as usize,
8751 ))
8752 }
8753 pub fn get_early_drop(&self) -> Result<u32, ErrorContext> {
8754 let mut iter = self.clone();
8755 iter.pos = 0;
8756 for attr in iter {
8757 if let OpGetStatsDumpReply::EarlyDrop(val) = attr? {
8758 return Ok(val);
8759 }
8760 }
8761 Err(ErrorContext::new_missing(
8762 "OpGetStatsDumpReply",
8763 "EarlyDrop",
8764 self.orig_loc,
8765 self.buf.as_ptr() as usize,
8766 ))
8767 }
8768 pub fn get_error(&self) -> Result<u32, ErrorContext> {
8769 let mut iter = self.clone();
8770 iter.pos = 0;
8771 for attr in iter {
8772 if let OpGetStatsDumpReply::Error(val) = attr? {
8773 return Ok(val);
8774 }
8775 }
8776 Err(ErrorContext::new_missing(
8777 "OpGetStatsDumpReply",
8778 "Error",
8779 self.orig_loc,
8780 self.buf.as_ptr() as usize,
8781 ))
8782 }
8783 pub fn get_search_restart(&self) -> Result<u32, ErrorContext> {
8784 let mut iter = self.clone();
8785 iter.pos = 0;
8786 for attr in iter {
8787 if let OpGetStatsDumpReply::SearchRestart(val) = attr? {
8788 return Ok(val);
8789 }
8790 }
8791 Err(ErrorContext::new_missing(
8792 "OpGetStatsDumpReply",
8793 "SearchRestart",
8794 self.orig_loc,
8795 self.buf.as_ptr() as usize,
8796 ))
8797 }
8798 pub fn get_clash_resolve(&self) -> Result<u32, ErrorContext> {
8799 let mut iter = self.clone();
8800 iter.pos = 0;
8801 for attr in iter {
8802 if let OpGetStatsDumpReply::ClashResolve(val) = attr? {
8803 return Ok(val);
8804 }
8805 }
8806 Err(ErrorContext::new_missing(
8807 "OpGetStatsDumpReply",
8808 "ClashResolve",
8809 self.orig_loc,
8810 self.buf.as_ptr() as usize,
8811 ))
8812 }
8813 pub fn get_chain_toolong(&self) -> Result<u32, ErrorContext> {
8814 let mut iter = self.clone();
8815 iter.pos = 0;
8816 for attr in iter {
8817 if let OpGetStatsDumpReply::ChainToolong(val) = attr? {
8818 return Ok(val);
8819 }
8820 }
8821 Err(ErrorContext::new_missing(
8822 "OpGetStatsDumpReply",
8823 "ChainToolong",
8824 self.orig_loc,
8825 self.buf.as_ptr() as usize,
8826 ))
8827 }
8828}
8829impl OpGetStatsDumpReply {
8830 pub fn new<'a>(buf: &'a [u8]) -> (PushNfgenmsg, IterableOpGetStatsDumpReply<'a>) {
8831 let (header, attrs) = buf.split_at(buf.len().min(PushNfgenmsg::len()));
8832 (
8833 PushNfgenmsg::new_from_slice(header).unwrap_or_default(),
8834 IterableOpGetStatsDumpReply::with_loc(attrs, buf.as_ptr() as usize),
8835 )
8836 }
8837 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8838 ConntrackStatsAttrs::attr_from_type(r#type)
8839 }
8840}
8841#[derive(Clone, Copy, Default)]
8842pub struct IterableOpGetStatsDumpReply<'a> {
8843 buf: &'a [u8],
8844 pos: usize,
8845 orig_loc: usize,
8846}
8847impl<'a> IterableOpGetStatsDumpReply<'a> {
8848 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8849 Self {
8850 buf,
8851 pos: 0,
8852 orig_loc,
8853 }
8854 }
8855 pub fn get_buf(&self) -> &'a [u8] {
8856 self.buf
8857 }
8858}
8859impl<'a> Iterator for IterableOpGetStatsDumpReply<'a> {
8860 type Item = Result<OpGetStatsDumpReply, ErrorContext>;
8861 fn next(&mut self) -> Option<Self::Item> {
8862 let pos = self.pos;
8863 let mut r#type;
8864 loop {
8865 r#type = None;
8866 if self.buf.len() == self.pos {
8867 return None;
8868 }
8869 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8870 break;
8871 };
8872 r#type = Some(header.r#type);
8873 let res = match header.r#type {
8874 1u16 => OpGetStatsDumpReply::Searched({
8875 let res = parse_be_u32(next);
8876 let Some(val) = res else { break };
8877 val
8878 }),
8879 2u16 => OpGetStatsDumpReply::Found({
8880 let res = parse_be_u32(next);
8881 let Some(val) = res else { break };
8882 val
8883 }),
8884 8u16 => OpGetStatsDumpReply::Insert({
8885 let res = parse_be_u32(next);
8886 let Some(val) = res else { break };
8887 val
8888 }),
8889 9u16 => OpGetStatsDumpReply::InsertFailed({
8890 let res = parse_be_u32(next);
8891 let Some(val) = res else { break };
8892 val
8893 }),
8894 10u16 => OpGetStatsDumpReply::Drop({
8895 let res = parse_be_u32(next);
8896 let Some(val) = res else { break };
8897 val
8898 }),
8899 11u16 => OpGetStatsDumpReply::EarlyDrop({
8900 let res = parse_be_u32(next);
8901 let Some(val) = res else { break };
8902 val
8903 }),
8904 12u16 => OpGetStatsDumpReply::Error({
8905 let res = parse_be_u32(next);
8906 let Some(val) = res else { break };
8907 val
8908 }),
8909 13u16 => OpGetStatsDumpReply::SearchRestart({
8910 let res = parse_be_u32(next);
8911 let Some(val) = res else { break };
8912 val
8913 }),
8914 14u16 => OpGetStatsDumpReply::ClashResolve({
8915 let res = parse_be_u32(next);
8916 let Some(val) = res else { break };
8917 val
8918 }),
8919 15u16 => OpGetStatsDumpReply::ChainToolong({
8920 let res = parse_be_u32(next);
8921 let Some(val) = res else { break };
8922 val
8923 }),
8924 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8925 n => continue,
8926 };
8927 return Some(Ok(res));
8928 }
8929 Some(Err(ErrorContext::new(
8930 "OpGetStatsDumpReply",
8931 r#type.and_then(|t| OpGetStatsDumpReply::attr_from_type(t)),
8932 self.orig_loc,
8933 self.buf.as_ptr().wrapping_add(pos) as usize,
8934 )))
8935 }
8936}
8937impl std::fmt::Debug for IterableOpGetStatsDumpReply<'_> {
8938 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8939 let mut fmt = f.debug_struct("OpGetStatsDumpReply");
8940 for attr in self.clone() {
8941 let attr = match attr {
8942 Ok(a) => a,
8943 Err(err) => {
8944 fmt.finish()?;
8945 f.write_str("Err(")?;
8946 err.fmt(f)?;
8947 return f.write_str(")");
8948 }
8949 };
8950 match attr {
8951 OpGetStatsDumpReply::Searched(val) => fmt.field("Searched", &val),
8952 OpGetStatsDumpReply::Found(val) => fmt.field("Found", &val),
8953 OpGetStatsDumpReply::Insert(val) => fmt.field("Insert", &val),
8954 OpGetStatsDumpReply::InsertFailed(val) => fmt.field("InsertFailed", &val),
8955 OpGetStatsDumpReply::Drop(val) => fmt.field("Drop", &val),
8956 OpGetStatsDumpReply::EarlyDrop(val) => fmt.field("EarlyDrop", &val),
8957 OpGetStatsDumpReply::Error(val) => fmt.field("Error", &val),
8958 OpGetStatsDumpReply::SearchRestart(val) => fmt.field("SearchRestart", &val),
8959 OpGetStatsDumpReply::ClashResolve(val) => fmt.field("ClashResolve", &val),
8960 OpGetStatsDumpReply::ChainToolong(val) => fmt.field("ChainToolong", &val),
8961 };
8962 }
8963 fmt.finish()
8964 }
8965}
8966impl IterableOpGetStatsDumpReply<'_> {
8967 pub fn lookup_attr(
8968 &self,
8969 offset: usize,
8970 missing_type: Option<u16>,
8971 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8972 let mut stack = Vec::new();
8973 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8974 if cur == offset + PushNfgenmsg::len() {
8975 stack.push(("OpGetStatsDumpReply", offset));
8976 return (
8977 stack,
8978 missing_type.and_then(|t| OpGetStatsDumpReply::attr_from_type(t)),
8979 );
8980 }
8981 if cur > offset || cur + self.buf.len() < offset {
8982 return (stack, None);
8983 }
8984 let mut attrs = self.clone();
8985 let mut last_off = cur + attrs.pos;
8986 while let Some(attr) = attrs.next() {
8987 let Ok(attr) = attr else { break };
8988 match attr {
8989 OpGetStatsDumpReply::Searched(val) => {
8990 if last_off == offset {
8991 stack.push(("Searched", last_off));
8992 break;
8993 }
8994 }
8995 OpGetStatsDumpReply::Found(val) => {
8996 if last_off == offset {
8997 stack.push(("Found", last_off));
8998 break;
8999 }
9000 }
9001 OpGetStatsDumpReply::Insert(val) => {
9002 if last_off == offset {
9003 stack.push(("Insert", last_off));
9004 break;
9005 }
9006 }
9007 OpGetStatsDumpReply::InsertFailed(val) => {
9008 if last_off == offset {
9009 stack.push(("InsertFailed", last_off));
9010 break;
9011 }
9012 }
9013 OpGetStatsDumpReply::Drop(val) => {
9014 if last_off == offset {
9015 stack.push(("Drop", last_off));
9016 break;
9017 }
9018 }
9019 OpGetStatsDumpReply::EarlyDrop(val) => {
9020 if last_off == offset {
9021 stack.push(("EarlyDrop", last_off));
9022 break;
9023 }
9024 }
9025 OpGetStatsDumpReply::Error(val) => {
9026 if last_off == offset {
9027 stack.push(("Error", last_off));
9028 break;
9029 }
9030 }
9031 OpGetStatsDumpReply::SearchRestart(val) => {
9032 if last_off == offset {
9033 stack.push(("SearchRestart", last_off));
9034 break;
9035 }
9036 }
9037 OpGetStatsDumpReply::ClashResolve(val) => {
9038 if last_off == offset {
9039 stack.push(("ClashResolve", last_off));
9040 break;
9041 }
9042 }
9043 OpGetStatsDumpReply::ChainToolong(val) => {
9044 if last_off == offset {
9045 stack.push(("ChainToolong", last_off));
9046 break;
9047 }
9048 }
9049 _ => {}
9050 };
9051 last_off = cur + attrs.pos;
9052 }
9053 if !stack.is_empty() {
9054 stack.push(("OpGetStatsDumpReply", cur));
9055 }
9056 (stack, None)
9057 }
9058}
9059#[derive(Debug)]
9060pub struct RequestOpGetStatsDumpRequest<'r> {
9061 request: Request<'r>,
9062}
9063impl<'r> RequestOpGetStatsDumpRequest<'r> {
9064 pub fn new(mut request: Request<'r>, header: &PushNfgenmsg) -> Self {
9065 PushOpGetStatsDumpRequest::write_header(&mut request.buf_mut(), header);
9066 Self {
9067 request: request.set_dump(),
9068 }
9069 }
9070 pub fn encode(&mut self) -> PushOpGetStatsDumpRequest<&mut Vec<u8>> {
9071 PushOpGetStatsDumpRequest::new_without_header(self.request.buf_mut())
9072 }
9073 pub fn into_encoder(self) -> PushOpGetStatsDumpRequest<RequestBuf<'r>> {
9074 PushOpGetStatsDumpRequest::new_without_header(self.request.buf)
9075 }
9076 pub fn decode_request<'buf>(
9077 buf: &'buf [u8],
9078 ) -> (PushNfgenmsg, IterableOpGetStatsDumpRequest<'buf>) {
9079 OpGetStatsDumpRequest::new(buf)
9080 }
9081}
9082impl NetlinkRequest for RequestOpGetStatsDumpRequest<'_> {
9083 fn protocol(&self) -> Protocol {
9084 Protocol::Raw {
9085 protonum: 12u16,
9086 request_type: 260u16,
9087 }
9088 }
9089 fn flags(&self) -> u16 {
9090 self.request.flags
9091 }
9092 fn payload(&self) -> &[u8] {
9093 self.request.buf()
9094 }
9095 type ReplyType<'buf> = (PushNfgenmsg, IterableOpGetStatsDumpReply<'buf>);
9096 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9097 OpGetStatsDumpReply::new(buf)
9098 }
9099 fn lookup(
9100 buf: &[u8],
9101 offset: usize,
9102 missing_type: Option<u16>,
9103 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9104 OpGetStatsDumpRequest::new(buf)
9105 .1
9106 .lookup_attr(offset, missing_type)
9107 }
9108}
9109#[derive(Debug)]
9110pub struct ChainedFinal<'a> {
9111 inner: Chained<'a>,
9112}
9113#[derive(Debug)]
9114pub struct Chained<'a> {
9115 buf: RequestBuf<'a>,
9116 first_seq: u32,
9117 lookups: Vec<(&'static str, LookupFn)>,
9118 last_header_offset: usize,
9119 last_kind: Option<RequestInfo>,
9120}
9121impl<'a> ChainedFinal<'a> {
9122 pub fn into_chained(self) -> Chained<'a> {
9123 self.inner
9124 }
9125 pub fn buf(&self) -> &Vec<u8> {
9126 self.inner.buf()
9127 }
9128 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9129 self.inner.buf_mut()
9130 }
9131 fn get_index(&self, seq: u32) -> Option<u32> {
9132 let min = self.inner.first_seq;
9133 let max = min.wrapping_add(self.inner.lookups.len() as u32);
9134 return if min <= max {
9135 (min..max).contains(&seq).then(|| seq - min)
9136 } else if min <= seq {
9137 Some(seq - min)
9138 } else if seq < max {
9139 Some(u32::MAX - min + seq)
9140 } else {
9141 None
9142 };
9143 }
9144}
9145impl crate::traits::NetlinkChained for ChainedFinal<'_> {
9146 fn protonum(&self) -> u16 {
9147 PROTONUM
9148 }
9149 fn payload(&self) -> &[u8] {
9150 self.buf()
9151 }
9152 fn chain_len(&self) -> usize {
9153 self.inner.lookups.len()
9154 }
9155 fn get_index(&self, seq: u32) -> Option<usize> {
9156 self.get_index(seq).map(|n| n as usize)
9157 }
9158 fn name(&self, index: usize) -> &'static str {
9159 self.inner.lookups[index].0
9160 }
9161 fn lookup(&self, index: usize) -> LookupFn {
9162 self.inner.lookups[index].1
9163 }
9164}
9165impl Chained<'static> {
9166 pub fn new(first_seq: u32) -> Self {
9167 Self::new_from_buf(Vec::new(), first_seq)
9168 }
9169 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
9170 Self {
9171 buf: RequestBuf::Own(buf),
9172 first_seq,
9173 lookups: Vec::new(),
9174 last_header_offset: 0,
9175 last_kind: None,
9176 }
9177 }
9178 pub fn into_buf(self) -> Vec<u8> {
9179 match self.buf {
9180 RequestBuf::Own(buf) => buf,
9181 _ => unreachable!(),
9182 }
9183 }
9184}
9185impl<'a> Chained<'a> {
9186 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
9187 Self {
9188 buf: RequestBuf::Ref(buf),
9189 first_seq,
9190 lookups: Vec::new(),
9191 last_header_offset: 0,
9192 last_kind: None,
9193 }
9194 }
9195 pub fn finalize(mut self) -> ChainedFinal<'a> {
9196 self.update_header();
9197 ChainedFinal { inner: self }
9198 }
9199 pub fn request(&mut self) -> Request<'_> {
9200 self.update_header();
9201 self.last_header_offset = self.buf().len();
9202 self.buf_mut()
9203 .extend_from_slice(PushNlmsghdr::new().as_slice());
9204 let mut request = Request::new_extend(self.buf.buf_mut());
9205 self.last_kind = None;
9206 request.writeback = Some(&mut self.last_kind);
9207 request
9208 }
9209 pub fn buf(&self) -> &Vec<u8> {
9210 self.buf.buf()
9211 }
9212 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9213 self.buf.buf_mut()
9214 }
9215 fn update_header(&mut self) {
9216 let Some(RequestInfo {
9217 protocol,
9218 flags,
9219 name,
9220 lookup,
9221 }) = self.last_kind
9222 else {
9223 if !self.buf().is_empty() {
9224 assert_eq!(
9225 self.last_header_offset + PushNlmsghdr::len(),
9226 self.buf().len()
9227 );
9228 self.buf.buf_mut().truncate(self.last_header_offset);
9229 }
9230 return;
9231 };
9232 let header_offset = self.last_header_offset;
9233 let request_type = match protocol {
9234 Protocol::Raw { request_type, .. } => request_type,
9235 Protocol::Generic(_) => unreachable!(),
9236 };
9237 let index = self.lookups.len();
9238 let seq = self.first_seq.wrapping_add(index as u32);
9239 self.lookups.push((name, lookup));
9240 let buf = self.buf_mut();
9241 align(buf);
9242 let mut header = PushNlmsghdr::new();
9243 header.set_len((buf.len() - header_offset) as u32);
9244 header.set_type(request_type);
9245 header.set_flags(flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16);
9246 header.set_seq(seq);
9247 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
9248 }
9249}
9250use crate::traits::LookupFn;
9251use crate::utils::RequestBuf;
9252#[derive(Debug)]
9253pub struct Request<'buf> {
9254 buf: RequestBuf<'buf>,
9255 flags: u16,
9256 writeback: Option<&'buf mut Option<RequestInfo>>,
9257}
9258#[allow(unused)]
9259#[derive(Debug, Clone)]
9260pub struct RequestInfo {
9261 protocol: Protocol,
9262 flags: u16,
9263 name: &'static str,
9264 lookup: LookupFn,
9265}
9266impl Request<'static> {
9267 pub fn new() -> Self {
9268 Self::new_from_buf(Vec::new())
9269 }
9270 pub fn new_from_buf(buf: Vec<u8>) -> Self {
9271 Self {
9272 flags: 0,
9273 buf: RequestBuf::Own(buf),
9274 writeback: None,
9275 }
9276 }
9277 pub fn into_buf(self) -> Vec<u8> {
9278 match self.buf {
9279 RequestBuf::Own(buf) => buf,
9280 _ => unreachable!(),
9281 }
9282 }
9283}
9284impl<'buf> Request<'buf> {
9285 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
9286 buf.clear();
9287 Self::new_extend(buf)
9288 }
9289 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
9290 Self {
9291 flags: 0,
9292 buf: RequestBuf::Ref(buf),
9293 writeback: None,
9294 }
9295 }
9296 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
9297 let Some(writeback) = &mut self.writeback else {
9298 return;
9299 };
9300 **writeback = Some(RequestInfo {
9301 protocol,
9302 flags: self.flags,
9303 name,
9304 lookup,
9305 })
9306 }
9307 pub fn buf(&self) -> &Vec<u8> {
9308 self.buf.buf()
9309 }
9310 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
9311 self.buf.buf_mut()
9312 }
9313 #[doc = "Set `NLM_F_CREATE` flag"]
9314 pub fn set_create(mut self) -> Self {
9315 self.flags |= consts::NLM_F_CREATE as u16;
9316 self
9317 }
9318 #[doc = "Set `NLM_F_EXCL` flag"]
9319 pub fn set_excl(mut self) -> Self {
9320 self.flags |= consts::NLM_F_EXCL as u16;
9321 self
9322 }
9323 #[doc = "Set `NLM_F_REPLACE` flag"]
9324 pub fn set_replace(mut self) -> Self {
9325 self.flags |= consts::NLM_F_REPLACE as u16;
9326 self
9327 }
9328 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
9329 pub fn set_change(self) -> Self {
9330 self.set_create().set_replace()
9331 }
9332 #[doc = "Set `NLM_F_APPEND` flag"]
9333 pub fn set_append(mut self) -> Self {
9334 self.flags |= consts::NLM_F_APPEND as u16;
9335 self
9336 }
9337 #[doc = "Set `NLM_F_DUMP` flag"]
9338 fn set_dump(mut self) -> Self {
9339 self.flags |= consts::NLM_F_DUMP as u16;
9340 self
9341 }
9342 pub fn op_get_dump_request(self, header: &PushNfgenmsg) -> RequestOpGetDumpRequest<'buf> {
9343 let mut res = RequestOpGetDumpRequest::new(self, header);
9344 res.request.do_writeback(
9345 res.protocol(),
9346 "op-get-dump-request",
9347 RequestOpGetDumpRequest::lookup,
9348 );
9349 res
9350 }
9351 pub fn op_get_do_request(self, header: &PushNfgenmsg) -> RequestOpGetDoRequest<'buf> {
9352 let mut res = RequestOpGetDoRequest::new(self, header);
9353 res.request.do_writeback(
9354 res.protocol(),
9355 "op-get-do-request",
9356 RequestOpGetDoRequest::lookup,
9357 );
9358 res
9359 }
9360 pub fn op_get_stats_dump_request(
9361 self,
9362 header: &PushNfgenmsg,
9363 ) -> RequestOpGetStatsDumpRequest<'buf> {
9364 let mut res = RequestOpGetStatsDumpRequest::new(self, header);
9365 res.request.do_writeback(
9366 res.protocol(),
9367 "op-get-stats-dump-request",
9368 RequestOpGetStatsDumpRequest::lookup,
9369 );
9370 res
9371 }
9372}