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