1#![doc = "Route configuration over rtnetlink.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "rt-route";
17pub const PROTONAME_CSTR: &CStr = c"rt-route";
18pub const PROTONUM: u16 = 0u16;
19#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
20#[derive(Debug, Clone, Copy)]
21pub enum RtmType {
22 Unspec = 0,
23 Unicast = 1,
24 Local = 2,
25 Broadcast = 3,
26 Anycast = 4,
27 Multicast = 5,
28 Blackhole = 6,
29 Unreachable = 7,
30 Prohibit = 8,
31 Throw = 9,
32 Nat = 10,
33 Xresolve = 11,
34}
35impl RtmType {
36 pub fn from_value(value: u64) -> Option<Self> {
37 Some(match value {
38 0 => Self::Unspec,
39 1 => Self::Unicast,
40 2 => Self::Local,
41 3 => Self::Broadcast,
42 4 => Self::Anycast,
43 5 => Self::Multicast,
44 6 => Self::Blackhole,
45 7 => Self::Unreachable,
46 8 => Self::Prohibit,
47 9 => Self::Throw,
48 10 => Self::Nat,
49 11 => Self::Xresolve,
50 _ => return None,
51 })
52 }
53}
54#[repr(C, packed(4))]
55pub struct Rtmsg {
56 pub rtm_family: u8,
57 pub rtm_dst_len: u8,
58 pub rtm_src_len: u8,
59 pub rtm_tos: u8,
60 pub rtm_table: u8,
61 pub rtm_protocol: u8,
62 pub rtm_scope: u8,
63 #[doc = "Associated type: [`RtmType`] (enum)"]
64 pub rtm_type: u8,
65 pub rtm_flags: u32,
66}
67impl Clone for Rtmsg {
68 fn clone(&self) -> Self {
69 Self::new_from_array(*self.as_array())
70 }
71}
72#[doc = "Create zero-initialized struct"]
73impl Default for Rtmsg {
74 fn default() -> Self {
75 Self::new()
76 }
77}
78impl Rtmsg {
79 #[doc = "Create zero-initialized struct"]
80 pub fn new() -> Self {
81 Self::new_from_array([0u8; Self::len()])
82 }
83 #[doc = "Copy from contents from slice"]
84 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
85 if other.len() != Self::len() {
86 return None;
87 }
88 let mut buf = [0u8; Self::len()];
89 buf.clone_from_slice(other);
90 Some(Self::new_from_array(buf))
91 }
92 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
93 pub fn new_from_zeroed(other: &[u8]) -> Self {
94 let mut buf = [0u8; Self::len()];
95 let len = buf.len().min(other.len());
96 buf[..len].clone_from_slice(&other[..len]);
97 Self::new_from_array(buf)
98 }
99 pub fn new_from_array(buf: [u8; 12usize]) -> Self {
100 unsafe { std::mem::transmute(buf) }
101 }
102 pub fn as_slice(&self) -> &[u8] {
103 unsafe {
104 let ptr: *const u8 = std::mem::transmute(self as *const Self);
105 std::slice::from_raw_parts(ptr, Self::len())
106 }
107 }
108 pub fn from_slice(buf: &[u8]) -> &Self {
109 assert!(buf.len() >= Self::len());
110 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
111 unsafe { std::mem::transmute(buf.as_ptr()) }
112 }
113 pub fn as_array(&self) -> &[u8; 12usize] {
114 unsafe { std::mem::transmute(self) }
115 }
116 pub fn from_array(buf: &[u8; 12usize]) -> &Self {
117 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
118 unsafe { std::mem::transmute(buf) }
119 }
120 pub fn into_array(self) -> [u8; 12usize] {
121 unsafe { std::mem::transmute(self) }
122 }
123 pub const fn len() -> usize {
124 const _: () = assert!(std::mem::size_of::<Rtmsg>() == 12usize);
125 12usize
126 }
127}
128impl std::fmt::Debug for Rtmsg {
129 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 fmt.debug_struct("Rtmsg")
131 .field("rtm_family", &self.rtm_family)
132 .field("rtm_dst_len", &self.rtm_dst_len)
133 .field("rtm_src_len", &self.rtm_src_len)
134 .field("rtm_tos", &self.rtm_tos)
135 .field("rtm_table", &self.rtm_table)
136 .field("rtm_protocol", &self.rtm_protocol)
137 .field("rtm_scope", &self.rtm_scope)
138 .field(
139 "rtm_type",
140 &FormatEnum(self.rtm_type.into(), RtmType::from_value),
141 )
142 .field("rtm_flags", &self.rtm_flags)
143 .finish()
144 }
145}
146#[derive(Debug)]
147#[repr(C, packed(4))]
148pub struct RtaCacheinfo {
149 pub rta_clntref: u32,
150 pub rta_lastuse: u32,
151 pub rta_expires: u32,
152 pub rta_error: u32,
153 pub rta_used: u32,
154}
155impl Clone for RtaCacheinfo {
156 fn clone(&self) -> Self {
157 Self::new_from_array(*self.as_array())
158 }
159}
160#[doc = "Create zero-initialized struct"]
161impl Default for RtaCacheinfo {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166impl RtaCacheinfo {
167 #[doc = "Create zero-initialized struct"]
168 pub fn new() -> Self {
169 Self::new_from_array([0u8; Self::len()])
170 }
171 #[doc = "Copy from contents from slice"]
172 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
173 if other.len() != Self::len() {
174 return None;
175 }
176 let mut buf = [0u8; Self::len()];
177 buf.clone_from_slice(other);
178 Some(Self::new_from_array(buf))
179 }
180 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
181 pub fn new_from_zeroed(other: &[u8]) -> Self {
182 let mut buf = [0u8; Self::len()];
183 let len = buf.len().min(other.len());
184 buf[..len].clone_from_slice(&other[..len]);
185 Self::new_from_array(buf)
186 }
187 pub fn new_from_array(buf: [u8; 20usize]) -> Self {
188 unsafe { std::mem::transmute(buf) }
189 }
190 pub fn as_slice(&self) -> &[u8] {
191 unsafe {
192 let ptr: *const u8 = std::mem::transmute(self as *const Self);
193 std::slice::from_raw_parts(ptr, Self::len())
194 }
195 }
196 pub fn from_slice(buf: &[u8]) -> &Self {
197 assert!(buf.len() >= Self::len());
198 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
199 unsafe { std::mem::transmute(buf.as_ptr()) }
200 }
201 pub fn as_array(&self) -> &[u8; 20usize] {
202 unsafe { std::mem::transmute(self) }
203 }
204 pub fn from_array(buf: &[u8; 20usize]) -> &Self {
205 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
206 unsafe { std::mem::transmute(buf) }
207 }
208 pub fn into_array(self) -> [u8; 20usize] {
209 unsafe { std::mem::transmute(self) }
210 }
211 pub const fn len() -> usize {
212 const _: () = assert!(std::mem::size_of::<RtaCacheinfo>() == 20usize);
213 20usize
214 }
215}
216#[derive(Clone)]
217pub enum RouteAttrs<'a> {
218 Dst(std::net::IpAddr),
219 Src(std::net::IpAddr),
220 Iif(u32),
221 Oif(u32),
222 Gateway(std::net::IpAddr),
223 Priority(u32),
224 Prefsrc(std::net::IpAddr),
225 Metrics(IterableMetrics<'a>),
226 Multipath(&'a [u8]),
227 Protoinfo(&'a [u8]),
228 Flow(u32),
229 Cacheinfo(RtaCacheinfo),
230 Session(&'a [u8]),
231 MpAlgo(&'a [u8]),
232 Table(u32),
233 Mark(u32),
234 MfcStats(&'a [u8]),
235 Via(&'a [u8]),
236 Newdst(&'a [u8]),
237 Pref(u8),
238 EncapType(u16),
239 Encap(&'a [u8]),
240 Expires(u32),
241 Pad(&'a [u8]),
242 Uid(u32),
243 TtlPropagate(u8),
244 IpProto(u8),
245 Sport(u16),
246 Dport(u16),
247 NhId(u32),
248 Flowlabel(u32),
249}
250impl<'a> IterableRouteAttrs<'a> {
251 pub fn get_dst(&self) -> Result<std::net::IpAddr, ErrorContext> {
252 let mut iter = self.clone();
253 iter.pos = 0;
254 for attr in iter {
255 if let Ok(RouteAttrs::Dst(val)) = attr {
256 return Ok(val);
257 }
258 }
259 Err(ErrorContext::new_missing(
260 "RouteAttrs",
261 "Dst",
262 self.orig_loc,
263 self.buf.as_ptr() as usize,
264 ))
265 }
266 pub fn get_src(&self) -> Result<std::net::IpAddr, ErrorContext> {
267 let mut iter = self.clone();
268 iter.pos = 0;
269 for attr in iter {
270 if let Ok(RouteAttrs::Src(val)) = attr {
271 return Ok(val);
272 }
273 }
274 Err(ErrorContext::new_missing(
275 "RouteAttrs",
276 "Src",
277 self.orig_loc,
278 self.buf.as_ptr() as usize,
279 ))
280 }
281 pub fn get_iif(&self) -> Result<u32, ErrorContext> {
282 let mut iter = self.clone();
283 iter.pos = 0;
284 for attr in iter {
285 if let Ok(RouteAttrs::Iif(val)) = attr {
286 return Ok(val);
287 }
288 }
289 Err(ErrorContext::new_missing(
290 "RouteAttrs",
291 "Iif",
292 self.orig_loc,
293 self.buf.as_ptr() as usize,
294 ))
295 }
296 pub fn get_oif(&self) -> Result<u32, ErrorContext> {
297 let mut iter = self.clone();
298 iter.pos = 0;
299 for attr in iter {
300 if let Ok(RouteAttrs::Oif(val)) = attr {
301 return Ok(val);
302 }
303 }
304 Err(ErrorContext::new_missing(
305 "RouteAttrs",
306 "Oif",
307 self.orig_loc,
308 self.buf.as_ptr() as usize,
309 ))
310 }
311 pub fn get_gateway(&self) -> Result<std::net::IpAddr, ErrorContext> {
312 let mut iter = self.clone();
313 iter.pos = 0;
314 for attr in iter {
315 if let Ok(RouteAttrs::Gateway(val)) = attr {
316 return Ok(val);
317 }
318 }
319 Err(ErrorContext::new_missing(
320 "RouteAttrs",
321 "Gateway",
322 self.orig_loc,
323 self.buf.as_ptr() as usize,
324 ))
325 }
326 pub fn get_priority(&self) -> Result<u32, ErrorContext> {
327 let mut iter = self.clone();
328 iter.pos = 0;
329 for attr in iter {
330 if let Ok(RouteAttrs::Priority(val)) = attr {
331 return Ok(val);
332 }
333 }
334 Err(ErrorContext::new_missing(
335 "RouteAttrs",
336 "Priority",
337 self.orig_loc,
338 self.buf.as_ptr() as usize,
339 ))
340 }
341 pub fn get_prefsrc(&self) -> Result<std::net::IpAddr, ErrorContext> {
342 let mut iter = self.clone();
343 iter.pos = 0;
344 for attr in iter {
345 if let Ok(RouteAttrs::Prefsrc(val)) = attr {
346 return Ok(val);
347 }
348 }
349 Err(ErrorContext::new_missing(
350 "RouteAttrs",
351 "Prefsrc",
352 self.orig_loc,
353 self.buf.as_ptr() as usize,
354 ))
355 }
356 pub fn get_metrics(&self) -> Result<IterableMetrics<'a>, ErrorContext> {
357 let mut iter = self.clone();
358 iter.pos = 0;
359 for attr in iter {
360 if let Ok(RouteAttrs::Metrics(val)) = attr {
361 return Ok(val);
362 }
363 }
364 Err(ErrorContext::new_missing(
365 "RouteAttrs",
366 "Metrics",
367 self.orig_loc,
368 self.buf.as_ptr() as usize,
369 ))
370 }
371 pub fn get_multipath(&self) -> Result<&'a [u8], ErrorContext> {
372 let mut iter = self.clone();
373 iter.pos = 0;
374 for attr in iter {
375 if let Ok(RouteAttrs::Multipath(val)) = attr {
376 return Ok(val);
377 }
378 }
379 Err(ErrorContext::new_missing(
380 "RouteAttrs",
381 "Multipath",
382 self.orig_loc,
383 self.buf.as_ptr() as usize,
384 ))
385 }
386 pub fn get_protoinfo(&self) -> Result<&'a [u8], ErrorContext> {
387 let mut iter = self.clone();
388 iter.pos = 0;
389 for attr in iter {
390 if let Ok(RouteAttrs::Protoinfo(val)) = attr {
391 return Ok(val);
392 }
393 }
394 Err(ErrorContext::new_missing(
395 "RouteAttrs",
396 "Protoinfo",
397 self.orig_loc,
398 self.buf.as_ptr() as usize,
399 ))
400 }
401 pub fn get_flow(&self) -> Result<u32, ErrorContext> {
402 let mut iter = self.clone();
403 iter.pos = 0;
404 for attr in iter {
405 if let Ok(RouteAttrs::Flow(val)) = attr {
406 return Ok(val);
407 }
408 }
409 Err(ErrorContext::new_missing(
410 "RouteAttrs",
411 "Flow",
412 self.orig_loc,
413 self.buf.as_ptr() as usize,
414 ))
415 }
416 pub fn get_cacheinfo(&self) -> Result<RtaCacheinfo, ErrorContext> {
417 let mut iter = self.clone();
418 iter.pos = 0;
419 for attr in iter {
420 if let Ok(RouteAttrs::Cacheinfo(val)) = attr {
421 return Ok(val);
422 }
423 }
424 Err(ErrorContext::new_missing(
425 "RouteAttrs",
426 "Cacheinfo",
427 self.orig_loc,
428 self.buf.as_ptr() as usize,
429 ))
430 }
431 pub fn get_session(&self) -> Result<&'a [u8], ErrorContext> {
432 let mut iter = self.clone();
433 iter.pos = 0;
434 for attr in iter {
435 if let Ok(RouteAttrs::Session(val)) = attr {
436 return Ok(val);
437 }
438 }
439 Err(ErrorContext::new_missing(
440 "RouteAttrs",
441 "Session",
442 self.orig_loc,
443 self.buf.as_ptr() as usize,
444 ))
445 }
446 pub fn get_mp_algo(&self) -> Result<&'a [u8], ErrorContext> {
447 let mut iter = self.clone();
448 iter.pos = 0;
449 for attr in iter {
450 if let Ok(RouteAttrs::MpAlgo(val)) = attr {
451 return Ok(val);
452 }
453 }
454 Err(ErrorContext::new_missing(
455 "RouteAttrs",
456 "MpAlgo",
457 self.orig_loc,
458 self.buf.as_ptr() as usize,
459 ))
460 }
461 pub fn get_table(&self) -> Result<u32, ErrorContext> {
462 let mut iter = self.clone();
463 iter.pos = 0;
464 for attr in iter {
465 if let Ok(RouteAttrs::Table(val)) = attr {
466 return Ok(val);
467 }
468 }
469 Err(ErrorContext::new_missing(
470 "RouteAttrs",
471 "Table",
472 self.orig_loc,
473 self.buf.as_ptr() as usize,
474 ))
475 }
476 pub fn get_mark(&self) -> Result<u32, ErrorContext> {
477 let mut iter = self.clone();
478 iter.pos = 0;
479 for attr in iter {
480 if let Ok(RouteAttrs::Mark(val)) = attr {
481 return Ok(val);
482 }
483 }
484 Err(ErrorContext::new_missing(
485 "RouteAttrs",
486 "Mark",
487 self.orig_loc,
488 self.buf.as_ptr() as usize,
489 ))
490 }
491 pub fn get_mfc_stats(&self) -> Result<&'a [u8], ErrorContext> {
492 let mut iter = self.clone();
493 iter.pos = 0;
494 for attr in iter {
495 if let Ok(RouteAttrs::MfcStats(val)) = attr {
496 return Ok(val);
497 }
498 }
499 Err(ErrorContext::new_missing(
500 "RouteAttrs",
501 "MfcStats",
502 self.orig_loc,
503 self.buf.as_ptr() as usize,
504 ))
505 }
506 pub fn get_via(&self) -> Result<&'a [u8], ErrorContext> {
507 let mut iter = self.clone();
508 iter.pos = 0;
509 for attr in iter {
510 if let Ok(RouteAttrs::Via(val)) = attr {
511 return Ok(val);
512 }
513 }
514 Err(ErrorContext::new_missing(
515 "RouteAttrs",
516 "Via",
517 self.orig_loc,
518 self.buf.as_ptr() as usize,
519 ))
520 }
521 pub fn get_newdst(&self) -> Result<&'a [u8], ErrorContext> {
522 let mut iter = self.clone();
523 iter.pos = 0;
524 for attr in iter {
525 if let Ok(RouteAttrs::Newdst(val)) = attr {
526 return Ok(val);
527 }
528 }
529 Err(ErrorContext::new_missing(
530 "RouteAttrs",
531 "Newdst",
532 self.orig_loc,
533 self.buf.as_ptr() as usize,
534 ))
535 }
536 pub fn get_pref(&self) -> Result<u8, ErrorContext> {
537 let mut iter = self.clone();
538 iter.pos = 0;
539 for attr in iter {
540 if let Ok(RouteAttrs::Pref(val)) = attr {
541 return Ok(val);
542 }
543 }
544 Err(ErrorContext::new_missing(
545 "RouteAttrs",
546 "Pref",
547 self.orig_loc,
548 self.buf.as_ptr() as usize,
549 ))
550 }
551 pub fn get_encap_type(&self) -> Result<u16, ErrorContext> {
552 let mut iter = self.clone();
553 iter.pos = 0;
554 for attr in iter {
555 if let Ok(RouteAttrs::EncapType(val)) = attr {
556 return Ok(val);
557 }
558 }
559 Err(ErrorContext::new_missing(
560 "RouteAttrs",
561 "EncapType",
562 self.orig_loc,
563 self.buf.as_ptr() as usize,
564 ))
565 }
566 pub fn get_encap(&self) -> Result<&'a [u8], ErrorContext> {
567 let mut iter = self.clone();
568 iter.pos = 0;
569 for attr in iter {
570 if let Ok(RouteAttrs::Encap(val)) = attr {
571 return Ok(val);
572 }
573 }
574 Err(ErrorContext::new_missing(
575 "RouteAttrs",
576 "Encap",
577 self.orig_loc,
578 self.buf.as_ptr() as usize,
579 ))
580 }
581 pub fn get_expires(&self) -> Result<u32, ErrorContext> {
582 let mut iter = self.clone();
583 iter.pos = 0;
584 for attr in iter {
585 if let Ok(RouteAttrs::Expires(val)) = attr {
586 return Ok(val);
587 }
588 }
589 Err(ErrorContext::new_missing(
590 "RouteAttrs",
591 "Expires",
592 self.orig_loc,
593 self.buf.as_ptr() as usize,
594 ))
595 }
596 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
597 let mut iter = self.clone();
598 iter.pos = 0;
599 for attr in iter {
600 if let Ok(RouteAttrs::Pad(val)) = attr {
601 return Ok(val);
602 }
603 }
604 Err(ErrorContext::new_missing(
605 "RouteAttrs",
606 "Pad",
607 self.orig_loc,
608 self.buf.as_ptr() as usize,
609 ))
610 }
611 pub fn get_uid(&self) -> Result<u32, ErrorContext> {
612 let mut iter = self.clone();
613 iter.pos = 0;
614 for attr in iter {
615 if let Ok(RouteAttrs::Uid(val)) = attr {
616 return Ok(val);
617 }
618 }
619 Err(ErrorContext::new_missing(
620 "RouteAttrs",
621 "Uid",
622 self.orig_loc,
623 self.buf.as_ptr() as usize,
624 ))
625 }
626 pub fn get_ttl_propagate(&self) -> Result<u8, ErrorContext> {
627 let mut iter = self.clone();
628 iter.pos = 0;
629 for attr in iter {
630 if let Ok(RouteAttrs::TtlPropagate(val)) = attr {
631 return Ok(val);
632 }
633 }
634 Err(ErrorContext::new_missing(
635 "RouteAttrs",
636 "TtlPropagate",
637 self.orig_loc,
638 self.buf.as_ptr() as usize,
639 ))
640 }
641 pub fn get_ip_proto(&self) -> Result<u8, ErrorContext> {
642 let mut iter = self.clone();
643 iter.pos = 0;
644 for attr in iter {
645 if let Ok(RouteAttrs::IpProto(val)) = attr {
646 return Ok(val);
647 }
648 }
649 Err(ErrorContext::new_missing(
650 "RouteAttrs",
651 "IpProto",
652 self.orig_loc,
653 self.buf.as_ptr() as usize,
654 ))
655 }
656 pub fn get_sport(&self) -> Result<u16, ErrorContext> {
657 let mut iter = self.clone();
658 iter.pos = 0;
659 for attr in iter {
660 if let Ok(RouteAttrs::Sport(val)) = attr {
661 return Ok(val);
662 }
663 }
664 Err(ErrorContext::new_missing(
665 "RouteAttrs",
666 "Sport",
667 self.orig_loc,
668 self.buf.as_ptr() as usize,
669 ))
670 }
671 pub fn get_dport(&self) -> Result<u16, ErrorContext> {
672 let mut iter = self.clone();
673 iter.pos = 0;
674 for attr in iter {
675 if let Ok(RouteAttrs::Dport(val)) = attr {
676 return Ok(val);
677 }
678 }
679 Err(ErrorContext::new_missing(
680 "RouteAttrs",
681 "Dport",
682 self.orig_loc,
683 self.buf.as_ptr() as usize,
684 ))
685 }
686 pub fn get_nh_id(&self) -> Result<u32, ErrorContext> {
687 let mut iter = self.clone();
688 iter.pos = 0;
689 for attr in iter {
690 if let Ok(RouteAttrs::NhId(val)) = attr {
691 return Ok(val);
692 }
693 }
694 Err(ErrorContext::new_missing(
695 "RouteAttrs",
696 "NhId",
697 self.orig_loc,
698 self.buf.as_ptr() as usize,
699 ))
700 }
701 pub fn get_flowlabel(&self) -> Result<u32, ErrorContext> {
702 let mut iter = self.clone();
703 iter.pos = 0;
704 for attr in iter {
705 if let Ok(RouteAttrs::Flowlabel(val)) = attr {
706 return Ok(val);
707 }
708 }
709 Err(ErrorContext::new_missing(
710 "RouteAttrs",
711 "Flowlabel",
712 self.orig_loc,
713 self.buf.as_ptr() as usize,
714 ))
715 }
716}
717impl RouteAttrs<'_> {
718 pub fn new<'a>(buf: &'a [u8]) -> IterableRouteAttrs<'a> {
719 IterableRouteAttrs::with_loc(buf, buf.as_ptr() as usize)
720 }
721 fn attr_from_type(r#type: u16) -> Option<&'static str> {
722 let res = match r#type {
723 1u16 => "Dst",
724 2u16 => "Src",
725 3u16 => "Iif",
726 4u16 => "Oif",
727 5u16 => "Gateway",
728 6u16 => "Priority",
729 7u16 => "Prefsrc",
730 8u16 => "Metrics",
731 9u16 => "Multipath",
732 10u16 => "Protoinfo",
733 11u16 => "Flow",
734 12u16 => "Cacheinfo",
735 13u16 => "Session",
736 14u16 => "MpAlgo",
737 15u16 => "Table",
738 16u16 => "Mark",
739 17u16 => "MfcStats",
740 18u16 => "Via",
741 19u16 => "Newdst",
742 20u16 => "Pref",
743 21u16 => "EncapType",
744 22u16 => "Encap",
745 23u16 => "Expires",
746 24u16 => "Pad",
747 25u16 => "Uid",
748 26u16 => "TtlPropagate",
749 27u16 => "IpProto",
750 28u16 => "Sport",
751 29u16 => "Dport",
752 30u16 => "NhId",
753 31u16 => "Flowlabel",
754 _ => return None,
755 };
756 Some(res)
757 }
758}
759#[derive(Clone, Copy, Default)]
760pub struct IterableRouteAttrs<'a> {
761 buf: &'a [u8],
762 pos: usize,
763 orig_loc: usize,
764}
765impl<'a> IterableRouteAttrs<'a> {
766 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
767 Self {
768 buf,
769 pos: 0,
770 orig_loc,
771 }
772 }
773 pub fn get_buf(&self) -> &'a [u8] {
774 self.buf
775 }
776}
777impl<'a> Iterator for IterableRouteAttrs<'a> {
778 type Item = Result<RouteAttrs<'a>, ErrorContext>;
779 fn next(&mut self) -> Option<Self::Item> {
780 let mut pos;
781 let mut r#type;
782 loop {
783 pos = self.pos;
784 r#type = None;
785 if self.buf.len() == self.pos {
786 return None;
787 }
788 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
789 self.pos = self.buf.len();
790 break;
791 };
792 r#type = Some(header.r#type);
793 let res = match header.r#type {
794 1u16 => RouteAttrs::Dst({
795 let res = parse_ip(next);
796 let Some(val) = res else { break };
797 val
798 }),
799 2u16 => RouteAttrs::Src({
800 let res = parse_ip(next);
801 let Some(val) = res else { break };
802 val
803 }),
804 3u16 => RouteAttrs::Iif({
805 let res = parse_u32(next);
806 let Some(val) = res else { break };
807 val
808 }),
809 4u16 => RouteAttrs::Oif({
810 let res = parse_u32(next);
811 let Some(val) = res else { break };
812 val
813 }),
814 5u16 => RouteAttrs::Gateway({
815 let res = parse_ip(next);
816 let Some(val) = res else { break };
817 val
818 }),
819 6u16 => RouteAttrs::Priority({
820 let res = parse_u32(next);
821 let Some(val) = res else { break };
822 val
823 }),
824 7u16 => RouteAttrs::Prefsrc({
825 let res = parse_ip(next);
826 let Some(val) = res else { break };
827 val
828 }),
829 8u16 => RouteAttrs::Metrics({
830 let res = Some(IterableMetrics::with_loc(next, self.orig_loc));
831 let Some(val) = res else { break };
832 val
833 }),
834 9u16 => RouteAttrs::Multipath({
835 let res = Some(next);
836 let Some(val) = res else { break };
837 val
838 }),
839 10u16 => RouteAttrs::Protoinfo({
840 let res = Some(next);
841 let Some(val) = res else { break };
842 val
843 }),
844 11u16 => RouteAttrs::Flow({
845 let res = parse_u32(next);
846 let Some(val) = res else { break };
847 val
848 }),
849 12u16 => RouteAttrs::Cacheinfo({
850 let res = Some(RtaCacheinfo::new_from_zeroed(next));
851 let Some(val) = res else { break };
852 val
853 }),
854 13u16 => RouteAttrs::Session({
855 let res = Some(next);
856 let Some(val) = res else { break };
857 val
858 }),
859 14u16 => RouteAttrs::MpAlgo({
860 let res = Some(next);
861 let Some(val) = res else { break };
862 val
863 }),
864 15u16 => RouteAttrs::Table({
865 let res = parse_u32(next);
866 let Some(val) = res else { break };
867 val
868 }),
869 16u16 => RouteAttrs::Mark({
870 let res = parse_u32(next);
871 let Some(val) = res else { break };
872 val
873 }),
874 17u16 => RouteAttrs::MfcStats({
875 let res = Some(next);
876 let Some(val) = res else { break };
877 val
878 }),
879 18u16 => RouteAttrs::Via({
880 let res = Some(next);
881 let Some(val) = res else { break };
882 val
883 }),
884 19u16 => RouteAttrs::Newdst({
885 let res = Some(next);
886 let Some(val) = res else { break };
887 val
888 }),
889 20u16 => RouteAttrs::Pref({
890 let res = parse_u8(next);
891 let Some(val) = res else { break };
892 val
893 }),
894 21u16 => RouteAttrs::EncapType({
895 let res = parse_u16(next);
896 let Some(val) = res else { break };
897 val
898 }),
899 22u16 => RouteAttrs::Encap({
900 let res = Some(next);
901 let Some(val) = res else { break };
902 val
903 }),
904 23u16 => RouteAttrs::Expires({
905 let res = parse_u32(next);
906 let Some(val) = res else { break };
907 val
908 }),
909 24u16 => RouteAttrs::Pad({
910 let res = Some(next);
911 let Some(val) = res else { break };
912 val
913 }),
914 25u16 => RouteAttrs::Uid({
915 let res = parse_u32(next);
916 let Some(val) = res else { break };
917 val
918 }),
919 26u16 => RouteAttrs::TtlPropagate({
920 let res = parse_u8(next);
921 let Some(val) = res else { break };
922 val
923 }),
924 27u16 => RouteAttrs::IpProto({
925 let res = parse_u8(next);
926 let Some(val) = res else { break };
927 val
928 }),
929 28u16 => RouteAttrs::Sport({
930 let res = parse_u16(next);
931 let Some(val) = res else { break };
932 val
933 }),
934 29u16 => RouteAttrs::Dport({
935 let res = parse_u16(next);
936 let Some(val) = res else { break };
937 val
938 }),
939 30u16 => RouteAttrs::NhId({
940 let res = parse_u32(next);
941 let Some(val) = res else { break };
942 val
943 }),
944 31u16 => RouteAttrs::Flowlabel({
945 let res = parse_be_u32(next);
946 let Some(val) = res else { break };
947 val
948 }),
949 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
950 n => continue,
951 };
952 return Some(Ok(res));
953 }
954 Some(Err(ErrorContext::new(
955 "RouteAttrs",
956 r#type.and_then(|t| RouteAttrs::attr_from_type(t)),
957 self.orig_loc,
958 self.buf.as_ptr().wrapping_add(pos) as usize,
959 )))
960 }
961}
962impl<'a> std::fmt::Debug for IterableRouteAttrs<'_> {
963 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
964 let mut fmt = f.debug_struct("RouteAttrs");
965 for attr in self.clone() {
966 let attr = match attr {
967 Ok(a) => a,
968 Err(err) => {
969 fmt.finish()?;
970 f.write_str("Err(")?;
971 err.fmt(f)?;
972 return f.write_str(")");
973 }
974 };
975 match attr {
976 RouteAttrs::Dst(val) => fmt.field("Dst", &val),
977 RouteAttrs::Src(val) => fmt.field("Src", &val),
978 RouteAttrs::Iif(val) => fmt.field("Iif", &val),
979 RouteAttrs::Oif(val) => fmt.field("Oif", &val),
980 RouteAttrs::Gateway(val) => fmt.field("Gateway", &val),
981 RouteAttrs::Priority(val) => fmt.field("Priority", &val),
982 RouteAttrs::Prefsrc(val) => fmt.field("Prefsrc", &val),
983 RouteAttrs::Metrics(val) => fmt.field("Metrics", &val),
984 RouteAttrs::Multipath(val) => fmt.field("Multipath", &val),
985 RouteAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
986 RouteAttrs::Flow(val) => fmt.field("Flow", &val),
987 RouteAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
988 RouteAttrs::Session(val) => fmt.field("Session", &val),
989 RouteAttrs::MpAlgo(val) => fmt.field("MpAlgo", &val),
990 RouteAttrs::Table(val) => fmt.field("Table", &val),
991 RouteAttrs::Mark(val) => fmt.field("Mark", &val),
992 RouteAttrs::MfcStats(val) => fmt.field("MfcStats", &val),
993 RouteAttrs::Via(val) => fmt.field("Via", &val),
994 RouteAttrs::Newdst(val) => fmt.field("Newdst", &val),
995 RouteAttrs::Pref(val) => fmt.field("Pref", &val),
996 RouteAttrs::EncapType(val) => fmt.field("EncapType", &val),
997 RouteAttrs::Encap(val) => fmt.field("Encap", &val),
998 RouteAttrs::Expires(val) => fmt.field("Expires", &val),
999 RouteAttrs::Pad(val) => fmt.field("Pad", &val),
1000 RouteAttrs::Uid(val) => fmt.field("Uid", &val),
1001 RouteAttrs::TtlPropagate(val) => fmt.field("TtlPropagate", &val),
1002 RouteAttrs::IpProto(val) => fmt.field("IpProto", &val),
1003 RouteAttrs::Sport(val) => fmt.field("Sport", &val),
1004 RouteAttrs::Dport(val) => fmt.field("Dport", &val),
1005 RouteAttrs::NhId(val) => fmt.field("NhId", &val),
1006 RouteAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1007 };
1008 }
1009 fmt.finish()
1010 }
1011}
1012impl IterableRouteAttrs<'_> {
1013 pub fn lookup_attr(
1014 &self,
1015 offset: usize,
1016 missing_type: Option<u16>,
1017 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1018 let mut stack = Vec::new();
1019 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1020 if missing_type.is_some() && cur == offset {
1021 stack.push(("RouteAttrs", offset));
1022 return (
1023 stack,
1024 missing_type.and_then(|t| RouteAttrs::attr_from_type(t)),
1025 );
1026 }
1027 if cur > offset || cur + self.buf.len() < offset {
1028 return (stack, None);
1029 }
1030 let mut attrs = self.clone();
1031 let mut last_off = cur + attrs.pos;
1032 let mut missing = None;
1033 while let Some(attr) = attrs.next() {
1034 let Ok(attr) = attr else { break };
1035 match attr {
1036 RouteAttrs::Dst(val) => {
1037 if last_off == offset {
1038 stack.push(("Dst", last_off));
1039 break;
1040 }
1041 }
1042 RouteAttrs::Src(val) => {
1043 if last_off == offset {
1044 stack.push(("Src", last_off));
1045 break;
1046 }
1047 }
1048 RouteAttrs::Iif(val) => {
1049 if last_off == offset {
1050 stack.push(("Iif", last_off));
1051 break;
1052 }
1053 }
1054 RouteAttrs::Oif(val) => {
1055 if last_off == offset {
1056 stack.push(("Oif", last_off));
1057 break;
1058 }
1059 }
1060 RouteAttrs::Gateway(val) => {
1061 if last_off == offset {
1062 stack.push(("Gateway", last_off));
1063 break;
1064 }
1065 }
1066 RouteAttrs::Priority(val) => {
1067 if last_off == offset {
1068 stack.push(("Priority", last_off));
1069 break;
1070 }
1071 }
1072 RouteAttrs::Prefsrc(val) => {
1073 if last_off == offset {
1074 stack.push(("Prefsrc", last_off));
1075 break;
1076 }
1077 }
1078 RouteAttrs::Metrics(val) => {
1079 (stack, missing) = val.lookup_attr(offset, missing_type);
1080 if !stack.is_empty() {
1081 break;
1082 }
1083 }
1084 RouteAttrs::Multipath(val) => {
1085 if last_off == offset {
1086 stack.push(("Multipath", last_off));
1087 break;
1088 }
1089 }
1090 RouteAttrs::Protoinfo(val) => {
1091 if last_off == offset {
1092 stack.push(("Protoinfo", last_off));
1093 break;
1094 }
1095 }
1096 RouteAttrs::Flow(val) => {
1097 if last_off == offset {
1098 stack.push(("Flow", last_off));
1099 break;
1100 }
1101 }
1102 RouteAttrs::Cacheinfo(val) => {
1103 if last_off == offset {
1104 stack.push(("Cacheinfo", last_off));
1105 break;
1106 }
1107 }
1108 RouteAttrs::Session(val) => {
1109 if last_off == offset {
1110 stack.push(("Session", last_off));
1111 break;
1112 }
1113 }
1114 RouteAttrs::MpAlgo(val) => {
1115 if last_off == offset {
1116 stack.push(("MpAlgo", last_off));
1117 break;
1118 }
1119 }
1120 RouteAttrs::Table(val) => {
1121 if last_off == offset {
1122 stack.push(("Table", last_off));
1123 break;
1124 }
1125 }
1126 RouteAttrs::Mark(val) => {
1127 if last_off == offset {
1128 stack.push(("Mark", last_off));
1129 break;
1130 }
1131 }
1132 RouteAttrs::MfcStats(val) => {
1133 if last_off == offset {
1134 stack.push(("MfcStats", last_off));
1135 break;
1136 }
1137 }
1138 RouteAttrs::Via(val) => {
1139 if last_off == offset {
1140 stack.push(("Via", last_off));
1141 break;
1142 }
1143 }
1144 RouteAttrs::Newdst(val) => {
1145 if last_off == offset {
1146 stack.push(("Newdst", last_off));
1147 break;
1148 }
1149 }
1150 RouteAttrs::Pref(val) => {
1151 if last_off == offset {
1152 stack.push(("Pref", last_off));
1153 break;
1154 }
1155 }
1156 RouteAttrs::EncapType(val) => {
1157 if last_off == offset {
1158 stack.push(("EncapType", last_off));
1159 break;
1160 }
1161 }
1162 RouteAttrs::Encap(val) => {
1163 if last_off == offset {
1164 stack.push(("Encap", last_off));
1165 break;
1166 }
1167 }
1168 RouteAttrs::Expires(val) => {
1169 if last_off == offset {
1170 stack.push(("Expires", last_off));
1171 break;
1172 }
1173 }
1174 RouteAttrs::Pad(val) => {
1175 if last_off == offset {
1176 stack.push(("Pad", last_off));
1177 break;
1178 }
1179 }
1180 RouteAttrs::Uid(val) => {
1181 if last_off == offset {
1182 stack.push(("Uid", last_off));
1183 break;
1184 }
1185 }
1186 RouteAttrs::TtlPropagate(val) => {
1187 if last_off == offset {
1188 stack.push(("TtlPropagate", last_off));
1189 break;
1190 }
1191 }
1192 RouteAttrs::IpProto(val) => {
1193 if last_off == offset {
1194 stack.push(("IpProto", last_off));
1195 break;
1196 }
1197 }
1198 RouteAttrs::Sport(val) => {
1199 if last_off == offset {
1200 stack.push(("Sport", last_off));
1201 break;
1202 }
1203 }
1204 RouteAttrs::Dport(val) => {
1205 if last_off == offset {
1206 stack.push(("Dport", last_off));
1207 break;
1208 }
1209 }
1210 RouteAttrs::NhId(val) => {
1211 if last_off == offset {
1212 stack.push(("NhId", last_off));
1213 break;
1214 }
1215 }
1216 RouteAttrs::Flowlabel(val) => {
1217 if last_off == offset {
1218 stack.push(("Flowlabel", last_off));
1219 break;
1220 }
1221 }
1222 _ => {}
1223 };
1224 last_off = cur + attrs.pos;
1225 }
1226 if !stack.is_empty() {
1227 stack.push(("RouteAttrs", cur));
1228 }
1229 (stack, missing)
1230 }
1231}
1232#[derive(Clone)]
1233pub enum Metrics<'a> {
1234 Lock(u32),
1235 Mtu(u32),
1236 Window(u32),
1237 Rtt(u32),
1238 Rttvar(u32),
1239 Ssthresh(u32),
1240 Cwnd(u32),
1241 Advmss(u32),
1242 Reordering(u32),
1243 Hoplimit(u32),
1244 Initcwnd(u32),
1245 Features(u32),
1246 RtoMin(u32),
1247 Initrwnd(u32),
1248 Quickack(u32),
1249 CcAlgo(&'a CStr),
1250 FastopenNoCookie(u32),
1251}
1252impl<'a> IterableMetrics<'a> {
1253 pub fn get_lock(&self) -> Result<u32, ErrorContext> {
1254 let mut iter = self.clone();
1255 iter.pos = 0;
1256 for attr in iter {
1257 if let Ok(Metrics::Lock(val)) = attr {
1258 return Ok(val);
1259 }
1260 }
1261 Err(ErrorContext::new_missing(
1262 "Metrics",
1263 "Lock",
1264 self.orig_loc,
1265 self.buf.as_ptr() as usize,
1266 ))
1267 }
1268 pub fn get_mtu(&self) -> Result<u32, ErrorContext> {
1269 let mut iter = self.clone();
1270 iter.pos = 0;
1271 for attr in iter {
1272 if let Ok(Metrics::Mtu(val)) = attr {
1273 return Ok(val);
1274 }
1275 }
1276 Err(ErrorContext::new_missing(
1277 "Metrics",
1278 "Mtu",
1279 self.orig_loc,
1280 self.buf.as_ptr() as usize,
1281 ))
1282 }
1283 pub fn get_window(&self) -> Result<u32, ErrorContext> {
1284 let mut iter = self.clone();
1285 iter.pos = 0;
1286 for attr in iter {
1287 if let Ok(Metrics::Window(val)) = attr {
1288 return Ok(val);
1289 }
1290 }
1291 Err(ErrorContext::new_missing(
1292 "Metrics",
1293 "Window",
1294 self.orig_loc,
1295 self.buf.as_ptr() as usize,
1296 ))
1297 }
1298 pub fn get_rtt(&self) -> Result<u32, ErrorContext> {
1299 let mut iter = self.clone();
1300 iter.pos = 0;
1301 for attr in iter {
1302 if let Ok(Metrics::Rtt(val)) = attr {
1303 return Ok(val);
1304 }
1305 }
1306 Err(ErrorContext::new_missing(
1307 "Metrics",
1308 "Rtt",
1309 self.orig_loc,
1310 self.buf.as_ptr() as usize,
1311 ))
1312 }
1313 pub fn get_rttvar(&self) -> Result<u32, ErrorContext> {
1314 let mut iter = self.clone();
1315 iter.pos = 0;
1316 for attr in iter {
1317 if let Ok(Metrics::Rttvar(val)) = attr {
1318 return Ok(val);
1319 }
1320 }
1321 Err(ErrorContext::new_missing(
1322 "Metrics",
1323 "Rttvar",
1324 self.orig_loc,
1325 self.buf.as_ptr() as usize,
1326 ))
1327 }
1328 pub fn get_ssthresh(&self) -> Result<u32, ErrorContext> {
1329 let mut iter = self.clone();
1330 iter.pos = 0;
1331 for attr in iter {
1332 if let Ok(Metrics::Ssthresh(val)) = attr {
1333 return Ok(val);
1334 }
1335 }
1336 Err(ErrorContext::new_missing(
1337 "Metrics",
1338 "Ssthresh",
1339 self.orig_loc,
1340 self.buf.as_ptr() as usize,
1341 ))
1342 }
1343 pub fn get_cwnd(&self) -> Result<u32, ErrorContext> {
1344 let mut iter = self.clone();
1345 iter.pos = 0;
1346 for attr in iter {
1347 if let Ok(Metrics::Cwnd(val)) = attr {
1348 return Ok(val);
1349 }
1350 }
1351 Err(ErrorContext::new_missing(
1352 "Metrics",
1353 "Cwnd",
1354 self.orig_loc,
1355 self.buf.as_ptr() as usize,
1356 ))
1357 }
1358 pub fn get_advmss(&self) -> Result<u32, ErrorContext> {
1359 let mut iter = self.clone();
1360 iter.pos = 0;
1361 for attr in iter {
1362 if let Ok(Metrics::Advmss(val)) = attr {
1363 return Ok(val);
1364 }
1365 }
1366 Err(ErrorContext::new_missing(
1367 "Metrics",
1368 "Advmss",
1369 self.orig_loc,
1370 self.buf.as_ptr() as usize,
1371 ))
1372 }
1373 pub fn get_reordering(&self) -> Result<u32, ErrorContext> {
1374 let mut iter = self.clone();
1375 iter.pos = 0;
1376 for attr in iter {
1377 if let Ok(Metrics::Reordering(val)) = attr {
1378 return Ok(val);
1379 }
1380 }
1381 Err(ErrorContext::new_missing(
1382 "Metrics",
1383 "Reordering",
1384 self.orig_loc,
1385 self.buf.as_ptr() as usize,
1386 ))
1387 }
1388 pub fn get_hoplimit(&self) -> Result<u32, ErrorContext> {
1389 let mut iter = self.clone();
1390 iter.pos = 0;
1391 for attr in iter {
1392 if let Ok(Metrics::Hoplimit(val)) = attr {
1393 return Ok(val);
1394 }
1395 }
1396 Err(ErrorContext::new_missing(
1397 "Metrics",
1398 "Hoplimit",
1399 self.orig_loc,
1400 self.buf.as_ptr() as usize,
1401 ))
1402 }
1403 pub fn get_initcwnd(&self) -> Result<u32, ErrorContext> {
1404 let mut iter = self.clone();
1405 iter.pos = 0;
1406 for attr in iter {
1407 if let Ok(Metrics::Initcwnd(val)) = attr {
1408 return Ok(val);
1409 }
1410 }
1411 Err(ErrorContext::new_missing(
1412 "Metrics",
1413 "Initcwnd",
1414 self.orig_loc,
1415 self.buf.as_ptr() as usize,
1416 ))
1417 }
1418 pub fn get_features(&self) -> Result<u32, ErrorContext> {
1419 let mut iter = self.clone();
1420 iter.pos = 0;
1421 for attr in iter {
1422 if let Ok(Metrics::Features(val)) = attr {
1423 return Ok(val);
1424 }
1425 }
1426 Err(ErrorContext::new_missing(
1427 "Metrics",
1428 "Features",
1429 self.orig_loc,
1430 self.buf.as_ptr() as usize,
1431 ))
1432 }
1433 pub fn get_rto_min(&self) -> Result<u32, ErrorContext> {
1434 let mut iter = self.clone();
1435 iter.pos = 0;
1436 for attr in iter {
1437 if let Ok(Metrics::RtoMin(val)) = attr {
1438 return Ok(val);
1439 }
1440 }
1441 Err(ErrorContext::new_missing(
1442 "Metrics",
1443 "RtoMin",
1444 self.orig_loc,
1445 self.buf.as_ptr() as usize,
1446 ))
1447 }
1448 pub fn get_initrwnd(&self) -> Result<u32, ErrorContext> {
1449 let mut iter = self.clone();
1450 iter.pos = 0;
1451 for attr in iter {
1452 if let Ok(Metrics::Initrwnd(val)) = attr {
1453 return Ok(val);
1454 }
1455 }
1456 Err(ErrorContext::new_missing(
1457 "Metrics",
1458 "Initrwnd",
1459 self.orig_loc,
1460 self.buf.as_ptr() as usize,
1461 ))
1462 }
1463 pub fn get_quickack(&self) -> Result<u32, ErrorContext> {
1464 let mut iter = self.clone();
1465 iter.pos = 0;
1466 for attr in iter {
1467 if let Ok(Metrics::Quickack(val)) = attr {
1468 return Ok(val);
1469 }
1470 }
1471 Err(ErrorContext::new_missing(
1472 "Metrics",
1473 "Quickack",
1474 self.orig_loc,
1475 self.buf.as_ptr() as usize,
1476 ))
1477 }
1478 pub fn get_cc_algo(&self) -> Result<&'a CStr, ErrorContext> {
1479 let mut iter = self.clone();
1480 iter.pos = 0;
1481 for attr in iter {
1482 if let Ok(Metrics::CcAlgo(val)) = attr {
1483 return Ok(val);
1484 }
1485 }
1486 Err(ErrorContext::new_missing(
1487 "Metrics",
1488 "CcAlgo",
1489 self.orig_loc,
1490 self.buf.as_ptr() as usize,
1491 ))
1492 }
1493 pub fn get_fastopen_no_cookie(&self) -> Result<u32, ErrorContext> {
1494 let mut iter = self.clone();
1495 iter.pos = 0;
1496 for attr in iter {
1497 if let Ok(Metrics::FastopenNoCookie(val)) = attr {
1498 return Ok(val);
1499 }
1500 }
1501 Err(ErrorContext::new_missing(
1502 "Metrics",
1503 "FastopenNoCookie",
1504 self.orig_loc,
1505 self.buf.as_ptr() as usize,
1506 ))
1507 }
1508}
1509impl Metrics<'_> {
1510 pub fn new<'a>(buf: &'a [u8]) -> IterableMetrics<'a> {
1511 IterableMetrics::with_loc(buf, buf.as_ptr() as usize)
1512 }
1513 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1514 let res = match r#type {
1515 0u16 => "Unspec",
1516 1u16 => "Lock",
1517 2u16 => "Mtu",
1518 3u16 => "Window",
1519 4u16 => "Rtt",
1520 5u16 => "Rttvar",
1521 6u16 => "Ssthresh",
1522 7u16 => "Cwnd",
1523 8u16 => "Advmss",
1524 9u16 => "Reordering",
1525 10u16 => "Hoplimit",
1526 11u16 => "Initcwnd",
1527 12u16 => "Features",
1528 13u16 => "RtoMin",
1529 14u16 => "Initrwnd",
1530 15u16 => "Quickack",
1531 16u16 => "CcAlgo",
1532 17u16 => "FastopenNoCookie",
1533 _ => return None,
1534 };
1535 Some(res)
1536 }
1537}
1538#[derive(Clone, Copy, Default)]
1539pub struct IterableMetrics<'a> {
1540 buf: &'a [u8],
1541 pos: usize,
1542 orig_loc: usize,
1543}
1544impl<'a> IterableMetrics<'a> {
1545 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1546 Self {
1547 buf,
1548 pos: 0,
1549 orig_loc,
1550 }
1551 }
1552 pub fn get_buf(&self) -> &'a [u8] {
1553 self.buf
1554 }
1555}
1556impl<'a> Iterator for IterableMetrics<'a> {
1557 type Item = Result<Metrics<'a>, ErrorContext>;
1558 fn next(&mut self) -> Option<Self::Item> {
1559 let mut pos;
1560 let mut r#type;
1561 loop {
1562 pos = self.pos;
1563 r#type = None;
1564 if self.buf.len() == self.pos {
1565 return None;
1566 }
1567 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1568 self.pos = self.buf.len();
1569 break;
1570 };
1571 r#type = Some(header.r#type);
1572 let res = match header.r#type {
1573 1u16 => Metrics::Lock({
1574 let res = parse_u32(next);
1575 let Some(val) = res else { break };
1576 val
1577 }),
1578 2u16 => Metrics::Mtu({
1579 let res = parse_u32(next);
1580 let Some(val) = res else { break };
1581 val
1582 }),
1583 3u16 => Metrics::Window({
1584 let res = parse_u32(next);
1585 let Some(val) = res else { break };
1586 val
1587 }),
1588 4u16 => Metrics::Rtt({
1589 let res = parse_u32(next);
1590 let Some(val) = res else { break };
1591 val
1592 }),
1593 5u16 => Metrics::Rttvar({
1594 let res = parse_u32(next);
1595 let Some(val) = res else { break };
1596 val
1597 }),
1598 6u16 => Metrics::Ssthresh({
1599 let res = parse_u32(next);
1600 let Some(val) = res else { break };
1601 val
1602 }),
1603 7u16 => Metrics::Cwnd({
1604 let res = parse_u32(next);
1605 let Some(val) = res else { break };
1606 val
1607 }),
1608 8u16 => Metrics::Advmss({
1609 let res = parse_u32(next);
1610 let Some(val) = res else { break };
1611 val
1612 }),
1613 9u16 => Metrics::Reordering({
1614 let res = parse_u32(next);
1615 let Some(val) = res else { break };
1616 val
1617 }),
1618 10u16 => Metrics::Hoplimit({
1619 let res = parse_u32(next);
1620 let Some(val) = res else { break };
1621 val
1622 }),
1623 11u16 => Metrics::Initcwnd({
1624 let res = parse_u32(next);
1625 let Some(val) = res else { break };
1626 val
1627 }),
1628 12u16 => Metrics::Features({
1629 let res = parse_u32(next);
1630 let Some(val) = res else { break };
1631 val
1632 }),
1633 13u16 => Metrics::RtoMin({
1634 let res = parse_u32(next);
1635 let Some(val) = res else { break };
1636 val
1637 }),
1638 14u16 => Metrics::Initrwnd({
1639 let res = parse_u32(next);
1640 let Some(val) = res else { break };
1641 val
1642 }),
1643 15u16 => Metrics::Quickack({
1644 let res = parse_u32(next);
1645 let Some(val) = res else { break };
1646 val
1647 }),
1648 16u16 => Metrics::CcAlgo({
1649 let res = CStr::from_bytes_with_nul(next).ok();
1650 let Some(val) = res else { break };
1651 val
1652 }),
1653 17u16 => Metrics::FastopenNoCookie({
1654 let res = parse_u32(next);
1655 let Some(val) = res else { break };
1656 val
1657 }),
1658 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1659 n => continue,
1660 };
1661 return Some(Ok(res));
1662 }
1663 Some(Err(ErrorContext::new(
1664 "Metrics",
1665 r#type.and_then(|t| Metrics::attr_from_type(t)),
1666 self.orig_loc,
1667 self.buf.as_ptr().wrapping_add(pos) as usize,
1668 )))
1669 }
1670}
1671impl<'a> std::fmt::Debug for IterableMetrics<'_> {
1672 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1673 let mut fmt = f.debug_struct("Metrics");
1674 for attr in self.clone() {
1675 let attr = match attr {
1676 Ok(a) => a,
1677 Err(err) => {
1678 fmt.finish()?;
1679 f.write_str("Err(")?;
1680 err.fmt(f)?;
1681 return f.write_str(")");
1682 }
1683 };
1684 match attr {
1685 Metrics::Lock(val) => fmt.field("Lock", &val),
1686 Metrics::Mtu(val) => fmt.field("Mtu", &val),
1687 Metrics::Window(val) => fmt.field("Window", &val),
1688 Metrics::Rtt(val) => fmt.field("Rtt", &val),
1689 Metrics::Rttvar(val) => fmt.field("Rttvar", &val),
1690 Metrics::Ssthresh(val) => fmt.field("Ssthresh", &val),
1691 Metrics::Cwnd(val) => fmt.field("Cwnd", &val),
1692 Metrics::Advmss(val) => fmt.field("Advmss", &val),
1693 Metrics::Reordering(val) => fmt.field("Reordering", &val),
1694 Metrics::Hoplimit(val) => fmt.field("Hoplimit", &val),
1695 Metrics::Initcwnd(val) => fmt.field("Initcwnd", &val),
1696 Metrics::Features(val) => fmt.field("Features", &val),
1697 Metrics::RtoMin(val) => fmt.field("RtoMin", &val),
1698 Metrics::Initrwnd(val) => fmt.field("Initrwnd", &val),
1699 Metrics::Quickack(val) => fmt.field("Quickack", &val),
1700 Metrics::CcAlgo(val) => fmt.field("CcAlgo", &val),
1701 Metrics::FastopenNoCookie(val) => fmt.field("FastopenNoCookie", &val),
1702 };
1703 }
1704 fmt.finish()
1705 }
1706}
1707impl IterableMetrics<'_> {
1708 pub fn lookup_attr(
1709 &self,
1710 offset: usize,
1711 missing_type: Option<u16>,
1712 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1713 let mut stack = Vec::new();
1714 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1715 if missing_type.is_some() && cur == offset {
1716 stack.push(("Metrics", offset));
1717 return (stack, missing_type.and_then(|t| Metrics::attr_from_type(t)));
1718 }
1719 if cur > offset || cur + self.buf.len() < offset {
1720 return (stack, None);
1721 }
1722 let mut attrs = self.clone();
1723 let mut last_off = cur + attrs.pos;
1724 while let Some(attr) = attrs.next() {
1725 let Ok(attr) = attr else { break };
1726 match attr {
1727 Metrics::Lock(val) => {
1728 if last_off == offset {
1729 stack.push(("Lock", last_off));
1730 break;
1731 }
1732 }
1733 Metrics::Mtu(val) => {
1734 if last_off == offset {
1735 stack.push(("Mtu", last_off));
1736 break;
1737 }
1738 }
1739 Metrics::Window(val) => {
1740 if last_off == offset {
1741 stack.push(("Window", last_off));
1742 break;
1743 }
1744 }
1745 Metrics::Rtt(val) => {
1746 if last_off == offset {
1747 stack.push(("Rtt", last_off));
1748 break;
1749 }
1750 }
1751 Metrics::Rttvar(val) => {
1752 if last_off == offset {
1753 stack.push(("Rttvar", last_off));
1754 break;
1755 }
1756 }
1757 Metrics::Ssthresh(val) => {
1758 if last_off == offset {
1759 stack.push(("Ssthresh", last_off));
1760 break;
1761 }
1762 }
1763 Metrics::Cwnd(val) => {
1764 if last_off == offset {
1765 stack.push(("Cwnd", last_off));
1766 break;
1767 }
1768 }
1769 Metrics::Advmss(val) => {
1770 if last_off == offset {
1771 stack.push(("Advmss", last_off));
1772 break;
1773 }
1774 }
1775 Metrics::Reordering(val) => {
1776 if last_off == offset {
1777 stack.push(("Reordering", last_off));
1778 break;
1779 }
1780 }
1781 Metrics::Hoplimit(val) => {
1782 if last_off == offset {
1783 stack.push(("Hoplimit", last_off));
1784 break;
1785 }
1786 }
1787 Metrics::Initcwnd(val) => {
1788 if last_off == offset {
1789 stack.push(("Initcwnd", last_off));
1790 break;
1791 }
1792 }
1793 Metrics::Features(val) => {
1794 if last_off == offset {
1795 stack.push(("Features", last_off));
1796 break;
1797 }
1798 }
1799 Metrics::RtoMin(val) => {
1800 if last_off == offset {
1801 stack.push(("RtoMin", last_off));
1802 break;
1803 }
1804 }
1805 Metrics::Initrwnd(val) => {
1806 if last_off == offset {
1807 stack.push(("Initrwnd", last_off));
1808 break;
1809 }
1810 }
1811 Metrics::Quickack(val) => {
1812 if last_off == offset {
1813 stack.push(("Quickack", last_off));
1814 break;
1815 }
1816 }
1817 Metrics::CcAlgo(val) => {
1818 if last_off == offset {
1819 stack.push(("CcAlgo", last_off));
1820 break;
1821 }
1822 }
1823 Metrics::FastopenNoCookie(val) => {
1824 if last_off == offset {
1825 stack.push(("FastopenNoCookie", last_off));
1826 break;
1827 }
1828 }
1829 _ => {}
1830 };
1831 last_off = cur + attrs.pos;
1832 }
1833 if !stack.is_empty() {
1834 stack.push(("Metrics", cur));
1835 }
1836 (stack, None)
1837 }
1838}
1839pub struct PushRouteAttrs<Prev: Rec> {
1840 pub(crate) prev: Option<Prev>,
1841 pub(crate) header_offset: Option<usize>,
1842}
1843impl<Prev: Rec> Rec for PushRouteAttrs<Prev> {
1844 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1845 self.prev.as_mut().unwrap().as_rec_mut()
1846 }
1847 fn as_rec(&self) -> &Vec<u8> {
1848 self.prev.as_ref().unwrap().as_rec()
1849 }
1850}
1851impl<Prev: Rec> PushRouteAttrs<Prev> {
1852 pub fn new(prev: Prev) -> Self {
1853 Self {
1854 prev: Some(prev),
1855 header_offset: None,
1856 }
1857 }
1858 pub fn end_nested(mut self) -> Prev {
1859 let mut prev = self.prev.take().unwrap();
1860 if let Some(header_offset) = &self.header_offset {
1861 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1862 }
1863 prev
1864 }
1865 pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1866 push_header(self.as_rec_mut(), 1u16, {
1867 match &value {
1868 IpAddr::V4(_) => 4,
1869 IpAddr::V6(_) => 16,
1870 }
1871 } as u16);
1872 encode_ip(self.as_rec_mut(), value);
1873 self
1874 }
1875 pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1876 push_header(self.as_rec_mut(), 2u16, {
1877 match &value {
1878 IpAddr::V4(_) => 4,
1879 IpAddr::V6(_) => 16,
1880 }
1881 } as u16);
1882 encode_ip(self.as_rec_mut(), value);
1883 self
1884 }
1885 pub fn push_iif(mut self, value: u32) -> Self {
1886 push_header(self.as_rec_mut(), 3u16, 4 as u16);
1887 self.as_rec_mut().extend(value.to_ne_bytes());
1888 self
1889 }
1890 pub fn push_oif(mut self, value: u32) -> Self {
1891 push_header(self.as_rec_mut(), 4u16, 4 as u16);
1892 self.as_rec_mut().extend(value.to_ne_bytes());
1893 self
1894 }
1895 pub fn push_gateway(mut self, value: std::net::IpAddr) -> Self {
1896 push_header(self.as_rec_mut(), 5u16, {
1897 match &value {
1898 IpAddr::V4(_) => 4,
1899 IpAddr::V6(_) => 16,
1900 }
1901 } as u16);
1902 encode_ip(self.as_rec_mut(), value);
1903 self
1904 }
1905 pub fn push_priority(mut self, value: u32) -> Self {
1906 push_header(self.as_rec_mut(), 6u16, 4 as u16);
1907 self.as_rec_mut().extend(value.to_ne_bytes());
1908 self
1909 }
1910 pub fn push_prefsrc(mut self, value: std::net::IpAddr) -> Self {
1911 push_header(self.as_rec_mut(), 7u16, {
1912 match &value {
1913 IpAddr::V4(_) => 4,
1914 IpAddr::V6(_) => 16,
1915 }
1916 } as u16);
1917 encode_ip(self.as_rec_mut(), value);
1918 self
1919 }
1920 pub fn nested_metrics(mut self) -> PushMetrics<Self> {
1921 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1922 PushMetrics {
1923 prev: Some(self),
1924 header_offset: Some(header_offset),
1925 }
1926 }
1927 pub fn push_multipath(mut self, value: &[u8]) -> Self {
1928 push_header(self.as_rec_mut(), 9u16, value.len() as u16);
1929 self.as_rec_mut().extend(value);
1930 self
1931 }
1932 pub fn push_protoinfo(mut self, value: &[u8]) -> Self {
1933 push_header(self.as_rec_mut(), 10u16, value.len() as u16);
1934 self.as_rec_mut().extend(value);
1935 self
1936 }
1937 pub fn push_flow(mut self, value: u32) -> Self {
1938 push_header(self.as_rec_mut(), 11u16, 4 as u16);
1939 self.as_rec_mut().extend(value.to_ne_bytes());
1940 self
1941 }
1942 pub fn push_cacheinfo(mut self, value: RtaCacheinfo) -> Self {
1943 push_header(self.as_rec_mut(), 12u16, value.as_slice().len() as u16);
1944 self.as_rec_mut().extend(value.as_slice());
1945 self
1946 }
1947 pub fn push_session(mut self, value: &[u8]) -> Self {
1948 push_header(self.as_rec_mut(), 13u16, value.len() as u16);
1949 self.as_rec_mut().extend(value);
1950 self
1951 }
1952 pub fn push_mp_algo(mut self, value: &[u8]) -> Self {
1953 push_header(self.as_rec_mut(), 14u16, value.len() as u16);
1954 self.as_rec_mut().extend(value);
1955 self
1956 }
1957 pub fn push_table(mut self, value: u32) -> Self {
1958 push_header(self.as_rec_mut(), 15u16, 4 as u16);
1959 self.as_rec_mut().extend(value.to_ne_bytes());
1960 self
1961 }
1962 pub fn push_mark(mut self, value: u32) -> Self {
1963 push_header(self.as_rec_mut(), 16u16, 4 as u16);
1964 self.as_rec_mut().extend(value.to_ne_bytes());
1965 self
1966 }
1967 pub fn push_mfc_stats(mut self, value: &[u8]) -> Self {
1968 push_header(self.as_rec_mut(), 17u16, value.len() as u16);
1969 self.as_rec_mut().extend(value);
1970 self
1971 }
1972 pub fn push_via(mut self, value: &[u8]) -> Self {
1973 push_header(self.as_rec_mut(), 18u16, value.len() as u16);
1974 self.as_rec_mut().extend(value);
1975 self
1976 }
1977 pub fn push_newdst(mut self, value: &[u8]) -> Self {
1978 push_header(self.as_rec_mut(), 19u16, value.len() as u16);
1979 self.as_rec_mut().extend(value);
1980 self
1981 }
1982 pub fn push_pref(mut self, value: u8) -> Self {
1983 push_header(self.as_rec_mut(), 20u16, 1 as u16);
1984 self.as_rec_mut().extend(value.to_ne_bytes());
1985 self
1986 }
1987 pub fn push_encap_type(mut self, value: u16) -> Self {
1988 push_header(self.as_rec_mut(), 21u16, 2 as u16);
1989 self.as_rec_mut().extend(value.to_ne_bytes());
1990 self
1991 }
1992 pub fn push_encap(mut self, value: &[u8]) -> Self {
1993 push_header(self.as_rec_mut(), 22u16, value.len() as u16);
1994 self.as_rec_mut().extend(value);
1995 self
1996 }
1997 pub fn push_expires(mut self, value: u32) -> Self {
1998 push_header(self.as_rec_mut(), 23u16, 4 as u16);
1999 self.as_rec_mut().extend(value.to_ne_bytes());
2000 self
2001 }
2002 pub fn push_pad(mut self, value: &[u8]) -> Self {
2003 push_header(self.as_rec_mut(), 24u16, value.len() as u16);
2004 self.as_rec_mut().extend(value);
2005 self
2006 }
2007 pub fn push_uid(mut self, value: u32) -> Self {
2008 push_header(self.as_rec_mut(), 25u16, 4 as u16);
2009 self.as_rec_mut().extend(value.to_ne_bytes());
2010 self
2011 }
2012 pub fn push_ttl_propagate(mut self, value: u8) -> Self {
2013 push_header(self.as_rec_mut(), 26u16, 1 as u16);
2014 self.as_rec_mut().extend(value.to_ne_bytes());
2015 self
2016 }
2017 pub fn push_ip_proto(mut self, value: u8) -> Self {
2018 push_header(self.as_rec_mut(), 27u16, 1 as u16);
2019 self.as_rec_mut().extend(value.to_ne_bytes());
2020 self
2021 }
2022 pub fn push_sport(mut self, value: u16) -> Self {
2023 push_header(self.as_rec_mut(), 28u16, 2 as u16);
2024 self.as_rec_mut().extend(value.to_ne_bytes());
2025 self
2026 }
2027 pub fn push_dport(mut self, value: u16) -> Self {
2028 push_header(self.as_rec_mut(), 29u16, 2 as u16);
2029 self.as_rec_mut().extend(value.to_ne_bytes());
2030 self
2031 }
2032 pub fn push_nh_id(mut self, value: u32) -> Self {
2033 push_header(self.as_rec_mut(), 30u16, 4 as u16);
2034 self.as_rec_mut().extend(value.to_ne_bytes());
2035 self
2036 }
2037 pub fn push_flowlabel(mut self, value: u32) -> Self {
2038 push_header(self.as_rec_mut(), 31u16, 4 as u16);
2039 self.as_rec_mut().extend(value.to_be_bytes());
2040 self
2041 }
2042}
2043impl<Prev: Rec> Drop for PushRouteAttrs<Prev> {
2044 fn drop(&mut self) {
2045 if let Some(prev) = &mut self.prev {
2046 if let Some(header_offset) = &self.header_offset {
2047 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2048 }
2049 }
2050 }
2051}
2052pub struct PushMetrics<Prev: Rec> {
2053 pub(crate) prev: Option<Prev>,
2054 pub(crate) header_offset: Option<usize>,
2055}
2056impl<Prev: Rec> Rec for PushMetrics<Prev> {
2057 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2058 self.prev.as_mut().unwrap().as_rec_mut()
2059 }
2060 fn as_rec(&self) -> &Vec<u8> {
2061 self.prev.as_ref().unwrap().as_rec()
2062 }
2063}
2064impl<Prev: Rec> PushMetrics<Prev> {
2065 pub fn new(prev: Prev) -> Self {
2066 Self {
2067 prev: Some(prev),
2068 header_offset: None,
2069 }
2070 }
2071 pub fn end_nested(mut self) -> Prev {
2072 let mut prev = self.prev.take().unwrap();
2073 if let Some(header_offset) = &self.header_offset {
2074 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2075 }
2076 prev
2077 }
2078 pub fn push_lock(mut self, value: u32) -> Self {
2079 push_header(self.as_rec_mut(), 1u16, 4 as u16);
2080 self.as_rec_mut().extend(value.to_ne_bytes());
2081 self
2082 }
2083 pub fn push_mtu(mut self, value: u32) -> Self {
2084 push_header(self.as_rec_mut(), 2u16, 4 as u16);
2085 self.as_rec_mut().extend(value.to_ne_bytes());
2086 self
2087 }
2088 pub fn push_window(mut self, value: u32) -> Self {
2089 push_header(self.as_rec_mut(), 3u16, 4 as u16);
2090 self.as_rec_mut().extend(value.to_ne_bytes());
2091 self
2092 }
2093 pub fn push_rtt(mut self, value: u32) -> Self {
2094 push_header(self.as_rec_mut(), 4u16, 4 as u16);
2095 self.as_rec_mut().extend(value.to_ne_bytes());
2096 self
2097 }
2098 pub fn push_rttvar(mut self, value: u32) -> Self {
2099 push_header(self.as_rec_mut(), 5u16, 4 as u16);
2100 self.as_rec_mut().extend(value.to_ne_bytes());
2101 self
2102 }
2103 pub fn push_ssthresh(mut self, value: u32) -> Self {
2104 push_header(self.as_rec_mut(), 6u16, 4 as u16);
2105 self.as_rec_mut().extend(value.to_ne_bytes());
2106 self
2107 }
2108 pub fn push_cwnd(mut self, value: u32) -> Self {
2109 push_header(self.as_rec_mut(), 7u16, 4 as u16);
2110 self.as_rec_mut().extend(value.to_ne_bytes());
2111 self
2112 }
2113 pub fn push_advmss(mut self, value: u32) -> Self {
2114 push_header(self.as_rec_mut(), 8u16, 4 as u16);
2115 self.as_rec_mut().extend(value.to_ne_bytes());
2116 self
2117 }
2118 pub fn push_reordering(mut self, value: u32) -> Self {
2119 push_header(self.as_rec_mut(), 9u16, 4 as u16);
2120 self.as_rec_mut().extend(value.to_ne_bytes());
2121 self
2122 }
2123 pub fn push_hoplimit(mut self, value: u32) -> Self {
2124 push_header(self.as_rec_mut(), 10u16, 4 as u16);
2125 self.as_rec_mut().extend(value.to_ne_bytes());
2126 self
2127 }
2128 pub fn push_initcwnd(mut self, value: u32) -> Self {
2129 push_header(self.as_rec_mut(), 11u16, 4 as u16);
2130 self.as_rec_mut().extend(value.to_ne_bytes());
2131 self
2132 }
2133 pub fn push_features(mut self, value: u32) -> Self {
2134 push_header(self.as_rec_mut(), 12u16, 4 as u16);
2135 self.as_rec_mut().extend(value.to_ne_bytes());
2136 self
2137 }
2138 pub fn push_rto_min(mut self, value: u32) -> Self {
2139 push_header(self.as_rec_mut(), 13u16, 4 as u16);
2140 self.as_rec_mut().extend(value.to_ne_bytes());
2141 self
2142 }
2143 pub fn push_initrwnd(mut self, value: u32) -> Self {
2144 push_header(self.as_rec_mut(), 14u16, 4 as u16);
2145 self.as_rec_mut().extend(value.to_ne_bytes());
2146 self
2147 }
2148 pub fn push_quickack(mut self, value: u32) -> Self {
2149 push_header(self.as_rec_mut(), 15u16, 4 as u16);
2150 self.as_rec_mut().extend(value.to_ne_bytes());
2151 self
2152 }
2153 pub fn push_cc_algo(mut self, value: &CStr) -> Self {
2154 push_header(
2155 self.as_rec_mut(),
2156 16u16,
2157 value.to_bytes_with_nul().len() as u16,
2158 );
2159 self.as_rec_mut().extend(value.to_bytes_with_nul());
2160 self
2161 }
2162 pub fn push_cc_algo_bytes(mut self, value: &[u8]) -> Self {
2163 push_header(self.as_rec_mut(), 16u16, (value.len() + 1) as u16);
2164 self.as_rec_mut().extend(value);
2165 self.as_rec_mut().push(0);
2166 self
2167 }
2168 pub fn push_fastopen_no_cookie(mut self, value: u32) -> Self {
2169 push_header(self.as_rec_mut(), 17u16, 4 as u16);
2170 self.as_rec_mut().extend(value.to_ne_bytes());
2171 self
2172 }
2173}
2174impl<Prev: Rec> Drop for PushMetrics<Prev> {
2175 fn drop(&mut self) {
2176 if let Some(prev) = &mut self.prev {
2177 if let Some(header_offset) = &self.header_offset {
2178 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2179 }
2180 }
2181 }
2182}
2183#[doc = "Dump route information.\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n\n"]
2184#[derive(Debug)]
2185pub struct OpGetrouteDump<'r> {
2186 request: Request<'r>,
2187}
2188impl<'r> OpGetrouteDump<'r> {
2189 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2190 Self::write_header(request.buf_mut(), header);
2191 Self {
2192 request: request.set_dump(),
2193 }
2194 }
2195 pub fn encode_request<'buf>(
2196 buf: &'buf mut Vec<u8>,
2197 header: &Rtmsg,
2198 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2199 Self::write_header(buf, header);
2200 PushRouteAttrs::new(buf)
2201 }
2202 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2203 PushRouteAttrs::new(self.request.buf_mut())
2204 }
2205 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2206 PushRouteAttrs::new(self.request.buf)
2207 }
2208 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2209 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2210 (
2211 Rtmsg::new_from_slice(header).unwrap_or_default(),
2212 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2213 )
2214 }
2215 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2216 prev.as_rec_mut().extend(header.as_slice());
2217 }
2218}
2219impl NetlinkRequest for OpGetrouteDump<'_> {
2220 fn protocol(&self) -> Protocol {
2221 Protocol::Raw {
2222 protonum: 0u16,
2223 request_type: 26u16,
2224 }
2225 }
2226 fn flags(&self) -> u16 {
2227 self.request.flags
2228 }
2229 fn payload(&self) -> &[u8] {
2230 self.request.buf()
2231 }
2232 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2233 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2234 Self::decode_request(buf)
2235 }
2236 fn lookup(
2237 buf: &[u8],
2238 offset: usize,
2239 missing_type: Option<u16>,
2240 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2241 Self::decode_request(buf)
2242 .1
2243 .lookup_attr(offset, missing_type)
2244 }
2245}
2246#[doc = "Dump route information.\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n\n"]
2247#[derive(Debug)]
2248pub struct OpGetrouteDo<'r> {
2249 request: Request<'r>,
2250}
2251impl<'r> OpGetrouteDo<'r> {
2252 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2253 Self::write_header(request.buf_mut(), header);
2254 Self { request: request }
2255 }
2256 pub fn encode_request<'buf>(
2257 buf: &'buf mut Vec<u8>,
2258 header: &Rtmsg,
2259 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2260 Self::write_header(buf, header);
2261 PushRouteAttrs::new(buf)
2262 }
2263 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2264 PushRouteAttrs::new(self.request.buf_mut())
2265 }
2266 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2267 PushRouteAttrs::new(self.request.buf)
2268 }
2269 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2270 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2271 (
2272 Rtmsg::new_from_slice(header).unwrap_or_default(),
2273 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2274 )
2275 }
2276 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2277 prev.as_rec_mut().extend(header.as_slice());
2278 }
2279}
2280impl NetlinkRequest for OpGetrouteDo<'_> {
2281 fn protocol(&self) -> Protocol {
2282 Protocol::Raw {
2283 protonum: 0u16,
2284 request_type: 26u16,
2285 }
2286 }
2287 fn flags(&self) -> u16 {
2288 self.request.flags
2289 }
2290 fn payload(&self) -> &[u8] {
2291 self.request.buf()
2292 }
2293 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2294 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2295 Self::decode_request(buf)
2296 }
2297 fn lookup(
2298 buf: &[u8],
2299 offset: usize,
2300 missing_type: Option<u16>,
2301 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2302 Self::decode_request(buf)
2303 .1
2304 .lookup_attr(offset, missing_type)
2305 }
2306}
2307#[doc = "Create a new route\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\n"]
2308#[derive(Debug)]
2309pub struct OpNewrouteDo<'r> {
2310 request: Request<'r>,
2311}
2312impl<'r> OpNewrouteDo<'r> {
2313 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2314 Self::write_header(request.buf_mut(), header);
2315 Self { request: request }
2316 }
2317 pub fn encode_request<'buf>(
2318 buf: &'buf mut Vec<u8>,
2319 header: &Rtmsg,
2320 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2321 Self::write_header(buf, header);
2322 PushRouteAttrs::new(buf)
2323 }
2324 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2325 PushRouteAttrs::new(self.request.buf_mut())
2326 }
2327 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2328 PushRouteAttrs::new(self.request.buf)
2329 }
2330 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2331 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2332 (
2333 Rtmsg::new_from_slice(header).unwrap_or_default(),
2334 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2335 )
2336 }
2337 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2338 prev.as_rec_mut().extend(header.as_slice());
2339 }
2340}
2341impl NetlinkRequest for OpNewrouteDo<'_> {
2342 fn protocol(&self) -> Protocol {
2343 Protocol::Raw {
2344 protonum: 0u16,
2345 request_type: 24u16,
2346 }
2347 }
2348 fn flags(&self) -> u16 {
2349 self.request.flags
2350 }
2351 fn payload(&self) -> &[u8] {
2352 self.request.buf()
2353 }
2354 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2355 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2356 Self::decode_request(buf)
2357 }
2358 fn lookup(
2359 buf: &[u8],
2360 offset: usize,
2361 missing_type: Option<u16>,
2362 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2363 Self::decode_request(buf)
2364 .1
2365 .lookup_attr(offset, missing_type)
2366 }
2367}
2368#[doc = "Delete an existing route\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\n"]
2369#[derive(Debug)]
2370pub struct OpDelrouteDo<'r> {
2371 request: Request<'r>,
2372}
2373impl<'r> OpDelrouteDo<'r> {
2374 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2375 Self::write_header(request.buf_mut(), header);
2376 Self { request: request }
2377 }
2378 pub fn encode_request<'buf>(
2379 buf: &'buf mut Vec<u8>,
2380 header: &Rtmsg,
2381 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2382 Self::write_header(buf, header);
2383 PushRouteAttrs::new(buf)
2384 }
2385 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2386 PushRouteAttrs::new(self.request.buf_mut())
2387 }
2388 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2389 PushRouteAttrs::new(self.request.buf)
2390 }
2391 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2392 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2393 (
2394 Rtmsg::new_from_slice(header).unwrap_or_default(),
2395 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2396 )
2397 }
2398 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2399 prev.as_rec_mut().extend(header.as_slice());
2400 }
2401}
2402impl NetlinkRequest for OpDelrouteDo<'_> {
2403 fn protocol(&self) -> Protocol {
2404 Protocol::Raw {
2405 protonum: 0u16,
2406 request_type: 25u16,
2407 }
2408 }
2409 fn flags(&self) -> u16 {
2410 self.request.flags
2411 }
2412 fn payload(&self) -> &[u8] {
2413 self.request.buf()
2414 }
2415 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2416 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2417 Self::decode_request(buf)
2418 }
2419 fn lookup(
2420 buf: &[u8],
2421 offset: usize,
2422 missing_type: Option<u16>,
2423 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2424 Self::decode_request(buf)
2425 .1
2426 .lookup_attr(offset, missing_type)
2427 }
2428}
2429#[derive(Debug)]
2430pub struct ChainedFinal<'a> {
2431 inner: Chained<'a>,
2432}
2433#[derive(Debug)]
2434pub struct Chained<'a> {
2435 buf: RequestBuf<'a>,
2436 first_seq: u32,
2437 lookups: Vec<(&'static str, LookupFn)>,
2438 last_header_offset: usize,
2439 last_kind: Option<RequestInfo>,
2440}
2441impl<'a> ChainedFinal<'a> {
2442 pub fn into_chained(self) -> Chained<'a> {
2443 self.inner
2444 }
2445 pub fn buf(&self) -> &Vec<u8> {
2446 self.inner.buf()
2447 }
2448 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2449 self.inner.buf_mut()
2450 }
2451 fn get_index(&self, seq: u32) -> Option<u32> {
2452 let min = self.inner.first_seq;
2453 let max = min.wrapping_add(self.inner.lookups.len() as u32);
2454 return if min <= max {
2455 (min..max).contains(&seq).then(|| seq - min)
2456 } else if min <= seq {
2457 Some(seq - min)
2458 } else if seq < max {
2459 Some(u32::MAX - min + seq)
2460 } else {
2461 None
2462 };
2463 }
2464}
2465impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2466 fn protonum(&self) -> u16 {
2467 PROTONUM
2468 }
2469 fn payload(&self) -> &[u8] {
2470 self.buf()
2471 }
2472 fn chain_len(&self) -> usize {
2473 self.inner.lookups.len()
2474 }
2475 fn get_index(&self, seq: u32) -> Option<usize> {
2476 self.get_index(seq).map(|n| n as usize)
2477 }
2478 fn name(&self, index: usize) -> &'static str {
2479 self.inner.lookups[index].0
2480 }
2481 fn lookup(&self, index: usize) -> LookupFn {
2482 self.inner.lookups[index].1
2483 }
2484}
2485impl Chained<'static> {
2486 pub fn new(first_seq: u32) -> Self {
2487 Self::new_from_buf(Vec::new(), first_seq)
2488 }
2489 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
2490 Self {
2491 buf: RequestBuf::Own(buf),
2492 first_seq,
2493 lookups: Vec::new(),
2494 last_header_offset: 0,
2495 last_kind: None,
2496 }
2497 }
2498 pub fn into_buf(self) -> Vec<u8> {
2499 match self.buf {
2500 RequestBuf::Own(buf) => buf,
2501 _ => unreachable!(),
2502 }
2503 }
2504}
2505impl<'a> Chained<'a> {
2506 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
2507 Self {
2508 buf: RequestBuf::Ref(buf),
2509 first_seq,
2510 lookups: Vec::new(),
2511 last_header_offset: 0,
2512 last_kind: None,
2513 }
2514 }
2515 pub fn finalize(mut self) -> ChainedFinal<'a> {
2516 self.update_header();
2517 ChainedFinal { inner: self }
2518 }
2519 pub fn request(&mut self) -> Request<'_> {
2520 self.update_header();
2521 self.last_header_offset = self.buf().len();
2522 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
2523 let mut request = Request::new_extend(self.buf.buf_mut());
2524 self.last_kind = None;
2525 request.writeback = Some(&mut self.last_kind);
2526 request
2527 }
2528 pub fn buf(&self) -> &Vec<u8> {
2529 self.buf.buf()
2530 }
2531 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2532 self.buf.buf_mut()
2533 }
2534 fn update_header(&mut self) {
2535 let Some(RequestInfo {
2536 protocol,
2537 flags,
2538 name,
2539 lookup,
2540 }) = self.last_kind
2541 else {
2542 if !self.buf().is_empty() {
2543 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
2544 self.buf.buf_mut().truncate(self.last_header_offset);
2545 }
2546 return;
2547 };
2548 let header_offset = self.last_header_offset;
2549 let request_type = match protocol {
2550 Protocol::Raw { request_type, .. } => request_type,
2551 Protocol::Generic(_) => unreachable!(),
2552 };
2553 let index = self.lookups.len();
2554 let seq = self.first_seq.wrapping_add(index as u32);
2555 self.lookups.push((name, lookup));
2556 let buf = self.buf_mut();
2557 align(buf);
2558 let header = Nlmsghdr {
2559 len: (buf.len() - header_offset) as u32,
2560 r#type: request_type,
2561 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
2562 seq,
2563 pid: 0,
2564 };
2565 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
2566 }
2567}
2568use crate::traits::LookupFn;
2569use crate::utils::RequestBuf;
2570#[derive(Debug)]
2571pub struct Request<'buf> {
2572 buf: RequestBuf<'buf>,
2573 flags: u16,
2574 writeback: Option<&'buf mut Option<RequestInfo>>,
2575}
2576#[allow(unused)]
2577#[derive(Debug, Clone)]
2578pub struct RequestInfo {
2579 protocol: Protocol,
2580 flags: u16,
2581 name: &'static str,
2582 lookup: LookupFn,
2583}
2584impl Request<'static> {
2585 pub fn new() -> Self {
2586 Self::new_from_buf(Vec::new())
2587 }
2588 pub fn new_from_buf(buf: Vec<u8>) -> Self {
2589 Self {
2590 flags: 0,
2591 buf: RequestBuf::Own(buf),
2592 writeback: None,
2593 }
2594 }
2595 pub fn into_buf(self) -> Vec<u8> {
2596 match self.buf {
2597 RequestBuf::Own(buf) => buf,
2598 _ => unreachable!(),
2599 }
2600 }
2601}
2602impl<'buf> Request<'buf> {
2603 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
2604 buf.clear();
2605 Self::new_extend(buf)
2606 }
2607 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
2608 Self {
2609 flags: 0,
2610 buf: RequestBuf::Ref(buf),
2611 writeback: None,
2612 }
2613 }
2614 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
2615 let Some(writeback) = &mut self.writeback else {
2616 return;
2617 };
2618 **writeback = Some(RequestInfo {
2619 protocol,
2620 flags: self.flags,
2621 name,
2622 lookup,
2623 })
2624 }
2625 pub fn buf(&self) -> &Vec<u8> {
2626 self.buf.buf()
2627 }
2628 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2629 self.buf.buf_mut()
2630 }
2631 #[doc = "Set `NLM_F_CREATE` flag"]
2632 pub fn set_create(mut self) -> Self {
2633 self.flags |= consts::NLM_F_CREATE as u16;
2634 self
2635 }
2636 #[doc = "Set `NLM_F_EXCL` flag"]
2637 pub fn set_excl(mut self) -> Self {
2638 self.flags |= consts::NLM_F_EXCL as u16;
2639 self
2640 }
2641 #[doc = "Set `NLM_F_REPLACE` flag"]
2642 pub fn set_replace(mut self) -> Self {
2643 self.flags |= consts::NLM_F_REPLACE as u16;
2644 self
2645 }
2646 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2647 pub fn set_change(self) -> Self {
2648 self.set_create().set_replace()
2649 }
2650 #[doc = "Set `NLM_F_APPEND` flag"]
2651 pub fn set_append(mut self) -> Self {
2652 self.flags |= consts::NLM_F_APPEND as u16;
2653 self
2654 }
2655 #[doc = "Set `self.flags |= flags`"]
2656 pub fn set_flags(mut self, flags: u16) -> Self {
2657 self.flags |= flags;
2658 self
2659 }
2660 #[doc = "Set `self.flags ^= self.flags & flags`"]
2661 pub fn unset_flags(mut self, flags: u16) -> Self {
2662 self.flags ^= self.flags & flags;
2663 self
2664 }
2665 #[doc = "Set `NLM_F_DUMP` flag"]
2666 fn set_dump(mut self) -> Self {
2667 self.flags |= consts::NLM_F_DUMP as u16;
2668 self
2669 }
2670 #[doc = "Dump route information.\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n\n"]
2671 pub fn op_getroute_dump(self, header: &Rtmsg) -> OpGetrouteDump<'buf> {
2672 let mut res = OpGetrouteDump::new(self, header);
2673 res.request
2674 .do_writeback(res.protocol(), "op-getroute-dump", OpGetrouteDump::lookup);
2675 res
2676 }
2677 #[doc = "Dump route information.\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\nReply attributes:\n- [.get_dst()](IterableRouteAttrs::get_dst)\n- [.get_src()](IterableRouteAttrs::get_src)\n- [.get_iif()](IterableRouteAttrs::get_iif)\n- [.get_oif()](IterableRouteAttrs::get_oif)\n- [.get_gateway()](IterableRouteAttrs::get_gateway)\n- [.get_priority()](IterableRouteAttrs::get_priority)\n- [.get_prefsrc()](IterableRouteAttrs::get_prefsrc)\n- [.get_metrics()](IterableRouteAttrs::get_metrics)\n- [.get_multipath()](IterableRouteAttrs::get_multipath)\n- [.get_flow()](IterableRouteAttrs::get_flow)\n- [.get_cacheinfo()](IterableRouteAttrs::get_cacheinfo)\n- [.get_table()](IterableRouteAttrs::get_table)\n- [.get_mark()](IterableRouteAttrs::get_mark)\n- [.get_mfc_stats()](IterableRouteAttrs::get_mfc_stats)\n- [.get_via()](IterableRouteAttrs::get_via)\n- [.get_newdst()](IterableRouteAttrs::get_newdst)\n- [.get_pref()](IterableRouteAttrs::get_pref)\n- [.get_encap_type()](IterableRouteAttrs::get_encap_type)\n- [.get_encap()](IterableRouteAttrs::get_encap)\n- [.get_expires()](IterableRouteAttrs::get_expires)\n- [.get_pad()](IterableRouteAttrs::get_pad)\n- [.get_uid()](IterableRouteAttrs::get_uid)\n- [.get_ttl_propagate()](IterableRouteAttrs::get_ttl_propagate)\n- [.get_ip_proto()](IterableRouteAttrs::get_ip_proto)\n- [.get_sport()](IterableRouteAttrs::get_sport)\n- [.get_dport()](IterableRouteAttrs::get_dport)\n- [.get_nh_id()](IterableRouteAttrs::get_nh_id)\n- [.get_flowlabel()](IterableRouteAttrs::get_flowlabel)\n\n"]
2678 pub fn op_getroute_do(self, header: &Rtmsg) -> OpGetrouteDo<'buf> {
2679 let mut res = OpGetrouteDo::new(self, header);
2680 res.request
2681 .do_writeback(res.protocol(), "op-getroute-do", OpGetrouteDo::lookup);
2682 res
2683 }
2684 #[doc = "Create a new route\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\n"]
2685 pub fn op_newroute_do(self, header: &Rtmsg) -> OpNewrouteDo<'buf> {
2686 let mut res = OpNewrouteDo::new(self, header);
2687 res.request
2688 .do_writeback(res.protocol(), "op-newroute-do", OpNewrouteDo::lookup);
2689 res
2690 }
2691 #[doc = "Delete an existing route\n\nRequest attributes:\n- [.push_dst()](PushRouteAttrs::push_dst)\n- [.push_src()](PushRouteAttrs::push_src)\n- [.push_iif()](PushRouteAttrs::push_iif)\n- [.push_oif()](PushRouteAttrs::push_oif)\n- [.push_gateway()](PushRouteAttrs::push_gateway)\n- [.push_priority()](PushRouteAttrs::push_priority)\n- [.push_prefsrc()](PushRouteAttrs::push_prefsrc)\n- [.nested_metrics()](PushRouteAttrs::nested_metrics)\n- [.push_multipath()](PushRouteAttrs::push_multipath)\n- [.push_flow()](PushRouteAttrs::push_flow)\n- [.push_cacheinfo()](PushRouteAttrs::push_cacheinfo)\n- [.push_table()](PushRouteAttrs::push_table)\n- [.push_mark()](PushRouteAttrs::push_mark)\n- [.push_mfc_stats()](PushRouteAttrs::push_mfc_stats)\n- [.push_via()](PushRouteAttrs::push_via)\n- [.push_newdst()](PushRouteAttrs::push_newdst)\n- [.push_pref()](PushRouteAttrs::push_pref)\n- [.push_encap_type()](PushRouteAttrs::push_encap_type)\n- [.push_encap()](PushRouteAttrs::push_encap)\n- [.push_expires()](PushRouteAttrs::push_expires)\n- [.push_pad()](PushRouteAttrs::push_pad)\n- [.push_uid()](PushRouteAttrs::push_uid)\n- [.push_ttl_propagate()](PushRouteAttrs::push_ttl_propagate)\n- [.push_ip_proto()](PushRouteAttrs::push_ip_proto)\n- [.push_sport()](PushRouteAttrs::push_sport)\n- [.push_dport()](PushRouteAttrs::push_dport)\n- [.push_nh_id()](PushRouteAttrs::push_nh_id)\n- [.push_flowlabel()](PushRouteAttrs::push_flowlabel)\n\n"]
2692 pub fn op_delroute_do(self, header: &Rtmsg) -> OpDelrouteDo<'buf> {
2693 let mut res = OpDelrouteDo::new(self, header);
2694 res.request
2695 .do_writeback(res.protocol(), "op-delroute-do", OpDelrouteDo::lookup);
2696 res
2697 }
2698}
2699#[cfg(test)]
2700mod generated_tests {
2701 use super::*;
2702 #[test]
2703 fn tests() {
2704 let _ = IterableRouteAttrs::get_cacheinfo;
2705 let _ = IterableRouteAttrs::get_dport;
2706 let _ = IterableRouteAttrs::get_dst;
2707 let _ = IterableRouteAttrs::get_encap;
2708 let _ = IterableRouteAttrs::get_encap_type;
2709 let _ = IterableRouteAttrs::get_expires;
2710 let _ = IterableRouteAttrs::get_flow;
2711 let _ = IterableRouteAttrs::get_flowlabel;
2712 let _ = IterableRouteAttrs::get_gateway;
2713 let _ = IterableRouteAttrs::get_iif;
2714 let _ = IterableRouteAttrs::get_ip_proto;
2715 let _ = IterableRouteAttrs::get_mark;
2716 let _ = IterableRouteAttrs::get_metrics;
2717 let _ = IterableRouteAttrs::get_mfc_stats;
2718 let _ = IterableRouteAttrs::get_multipath;
2719 let _ = IterableRouteAttrs::get_newdst;
2720 let _ = IterableRouteAttrs::get_nh_id;
2721 let _ = IterableRouteAttrs::get_oif;
2722 let _ = IterableRouteAttrs::get_pad;
2723 let _ = IterableRouteAttrs::get_pref;
2724 let _ = IterableRouteAttrs::get_prefsrc;
2725 let _ = IterableRouteAttrs::get_priority;
2726 let _ = IterableRouteAttrs::get_sport;
2727 let _ = IterableRouteAttrs::get_src;
2728 let _ = IterableRouteAttrs::get_table;
2729 let _ = IterableRouteAttrs::get_ttl_propagate;
2730 let _ = IterableRouteAttrs::get_uid;
2731 let _ = IterableRouteAttrs::get_via;
2732 let _ = PushRouteAttrs::<&mut Vec<u8>>::nested_metrics;
2733 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_cacheinfo;
2734 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dport;
2735 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dst;
2736 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap;
2737 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap_type;
2738 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_expires;
2739 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flow;
2740 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flowlabel;
2741 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_gateway;
2742 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_iif;
2743 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ip_proto;
2744 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mark;
2745 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mfc_stats;
2746 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_multipath;
2747 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_newdst;
2748 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_nh_id;
2749 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_oif;
2750 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pad;
2751 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pref;
2752 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_prefsrc;
2753 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_priority;
2754 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_sport;
2755 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_src;
2756 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_table;
2757 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ttl_propagate;
2758 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_uid;
2759 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_via;
2760 }
2761}