1#![doc = "Route configuration over rtnetlink\\."]
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pos = self.pos;
781 let mut r#type;
782 loop {
783 r#type = None;
784 if self.buf.len() == self.pos {
785 return None;
786 }
787 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
788 break;
789 };
790 r#type = Some(header.r#type);
791 let res = match header.r#type {
792 1u16 => RouteAttrs::Dst({
793 let res = parse_ip(next);
794 let Some(val) = res else { break };
795 val
796 }),
797 2u16 => RouteAttrs::Src({
798 let res = parse_ip(next);
799 let Some(val) = res else { break };
800 val
801 }),
802 3u16 => RouteAttrs::Iif({
803 let res = parse_u32(next);
804 let Some(val) = res else { break };
805 val
806 }),
807 4u16 => RouteAttrs::Oif({
808 let res = parse_u32(next);
809 let Some(val) = res else { break };
810 val
811 }),
812 5u16 => RouteAttrs::Gateway({
813 let res = parse_ip(next);
814 let Some(val) = res else { break };
815 val
816 }),
817 6u16 => RouteAttrs::Priority({
818 let res = parse_u32(next);
819 let Some(val) = res else { break };
820 val
821 }),
822 7u16 => RouteAttrs::Prefsrc({
823 let res = parse_ip(next);
824 let Some(val) = res else { break };
825 val
826 }),
827 8u16 => RouteAttrs::Metrics({
828 let res = Some(IterableMetrics::with_loc(next, self.orig_loc));
829 let Some(val) = res else { break };
830 val
831 }),
832 9u16 => RouteAttrs::Multipath({
833 let res = Some(next);
834 let Some(val) = res else { break };
835 val
836 }),
837 10u16 => RouteAttrs::Protoinfo({
838 let res = Some(next);
839 let Some(val) = res else { break };
840 val
841 }),
842 11u16 => RouteAttrs::Flow({
843 let res = parse_u32(next);
844 let Some(val) = res else { break };
845 val
846 }),
847 12u16 => RouteAttrs::Cacheinfo({
848 let res = Some(RtaCacheinfo::new_from_zeroed(next));
849 let Some(val) = res else { break };
850 val
851 }),
852 13u16 => RouteAttrs::Session({
853 let res = Some(next);
854 let Some(val) = res else { break };
855 val
856 }),
857 14u16 => RouteAttrs::MpAlgo({
858 let res = Some(next);
859 let Some(val) = res else { break };
860 val
861 }),
862 15u16 => RouteAttrs::Table({
863 let res = parse_u32(next);
864 let Some(val) = res else { break };
865 val
866 }),
867 16u16 => RouteAttrs::Mark({
868 let res = parse_u32(next);
869 let Some(val) = res else { break };
870 val
871 }),
872 17u16 => RouteAttrs::MfcStats({
873 let res = Some(next);
874 let Some(val) = res else { break };
875 val
876 }),
877 18u16 => RouteAttrs::Via({
878 let res = Some(next);
879 let Some(val) = res else { break };
880 val
881 }),
882 19u16 => RouteAttrs::Newdst({
883 let res = Some(next);
884 let Some(val) = res else { break };
885 val
886 }),
887 20u16 => RouteAttrs::Pref({
888 let res = parse_u8(next);
889 let Some(val) = res else { break };
890 val
891 }),
892 21u16 => RouteAttrs::EncapType({
893 let res = parse_u16(next);
894 let Some(val) = res else { break };
895 val
896 }),
897 22u16 => RouteAttrs::Encap({
898 let res = Some(next);
899 let Some(val) = res else { break };
900 val
901 }),
902 23u16 => RouteAttrs::Expires({
903 let res = parse_u32(next);
904 let Some(val) = res else { break };
905 val
906 }),
907 24u16 => RouteAttrs::Pad({
908 let res = Some(next);
909 let Some(val) = res else { break };
910 val
911 }),
912 25u16 => RouteAttrs::Uid({
913 let res = parse_u32(next);
914 let Some(val) = res else { break };
915 val
916 }),
917 26u16 => RouteAttrs::TtlPropagate({
918 let res = parse_u8(next);
919 let Some(val) = res else { break };
920 val
921 }),
922 27u16 => RouteAttrs::IpProto({
923 let res = parse_u8(next);
924 let Some(val) = res else { break };
925 val
926 }),
927 28u16 => RouteAttrs::Sport({
928 let res = parse_u16(next);
929 let Some(val) = res else { break };
930 val
931 }),
932 29u16 => RouteAttrs::Dport({
933 let res = parse_u16(next);
934 let Some(val) = res else { break };
935 val
936 }),
937 30u16 => RouteAttrs::NhId({
938 let res = parse_u32(next);
939 let Some(val) = res else { break };
940 val
941 }),
942 31u16 => RouteAttrs::Flowlabel({
943 let res = parse_be_u32(next);
944 let Some(val) = res else { break };
945 val
946 }),
947 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
948 n => continue,
949 };
950 return Some(Ok(res));
951 }
952 Some(Err(ErrorContext::new(
953 "RouteAttrs",
954 r#type.and_then(|t| RouteAttrs::attr_from_type(t)),
955 self.orig_loc,
956 self.buf.as_ptr().wrapping_add(pos) as usize,
957 )))
958 }
959}
960impl<'a> std::fmt::Debug for IterableRouteAttrs<'_> {
961 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
962 let mut fmt = f.debug_struct("RouteAttrs");
963 for attr in self.clone() {
964 let attr = match attr {
965 Ok(a) => a,
966 Err(err) => {
967 fmt.finish()?;
968 f.write_str("Err(")?;
969 err.fmt(f)?;
970 return f.write_str(")");
971 }
972 };
973 match attr {
974 RouteAttrs::Dst(val) => fmt.field("Dst", &val),
975 RouteAttrs::Src(val) => fmt.field("Src", &val),
976 RouteAttrs::Iif(val) => fmt.field("Iif", &val),
977 RouteAttrs::Oif(val) => fmt.field("Oif", &val),
978 RouteAttrs::Gateway(val) => fmt.field("Gateway", &val),
979 RouteAttrs::Priority(val) => fmt.field("Priority", &val),
980 RouteAttrs::Prefsrc(val) => fmt.field("Prefsrc", &val),
981 RouteAttrs::Metrics(val) => fmt.field("Metrics", &val),
982 RouteAttrs::Multipath(val) => fmt.field("Multipath", &val),
983 RouteAttrs::Protoinfo(val) => fmt.field("Protoinfo", &val),
984 RouteAttrs::Flow(val) => fmt.field("Flow", &val),
985 RouteAttrs::Cacheinfo(val) => fmt.field("Cacheinfo", &val),
986 RouteAttrs::Session(val) => fmt.field("Session", &val),
987 RouteAttrs::MpAlgo(val) => fmt.field("MpAlgo", &val),
988 RouteAttrs::Table(val) => fmt.field("Table", &val),
989 RouteAttrs::Mark(val) => fmt.field("Mark", &val),
990 RouteAttrs::MfcStats(val) => fmt.field("MfcStats", &val),
991 RouteAttrs::Via(val) => fmt.field("Via", &val),
992 RouteAttrs::Newdst(val) => fmt.field("Newdst", &val),
993 RouteAttrs::Pref(val) => fmt.field("Pref", &val),
994 RouteAttrs::EncapType(val) => fmt.field("EncapType", &val),
995 RouteAttrs::Encap(val) => fmt.field("Encap", &val),
996 RouteAttrs::Expires(val) => fmt.field("Expires", &val),
997 RouteAttrs::Pad(val) => fmt.field("Pad", &val),
998 RouteAttrs::Uid(val) => fmt.field("Uid", &val),
999 RouteAttrs::TtlPropagate(val) => fmt.field("TtlPropagate", &val),
1000 RouteAttrs::IpProto(val) => fmt.field("IpProto", &val),
1001 RouteAttrs::Sport(val) => fmt.field("Sport", &val),
1002 RouteAttrs::Dport(val) => fmt.field("Dport", &val),
1003 RouteAttrs::NhId(val) => fmt.field("NhId", &val),
1004 RouteAttrs::Flowlabel(val) => fmt.field("Flowlabel", &val),
1005 };
1006 }
1007 fmt.finish()
1008 }
1009}
1010impl IterableRouteAttrs<'_> {
1011 pub fn lookup_attr(
1012 &self,
1013 offset: usize,
1014 missing_type: Option<u16>,
1015 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1016 let mut stack = Vec::new();
1017 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1018 if missing_type.is_some() && cur == offset {
1019 stack.push(("RouteAttrs", offset));
1020 return (
1021 stack,
1022 missing_type.and_then(|t| RouteAttrs::attr_from_type(t)),
1023 );
1024 }
1025 if cur > offset || cur + self.buf.len() < offset {
1026 return (stack, None);
1027 }
1028 let mut attrs = self.clone();
1029 let mut last_off = cur + attrs.pos;
1030 let mut missing = None;
1031 while let Some(attr) = attrs.next() {
1032 let Ok(attr) = attr else { break };
1033 match attr {
1034 RouteAttrs::Dst(val) => {
1035 if last_off == offset {
1036 stack.push(("Dst", last_off));
1037 break;
1038 }
1039 }
1040 RouteAttrs::Src(val) => {
1041 if last_off == offset {
1042 stack.push(("Src", last_off));
1043 break;
1044 }
1045 }
1046 RouteAttrs::Iif(val) => {
1047 if last_off == offset {
1048 stack.push(("Iif", last_off));
1049 break;
1050 }
1051 }
1052 RouteAttrs::Oif(val) => {
1053 if last_off == offset {
1054 stack.push(("Oif", last_off));
1055 break;
1056 }
1057 }
1058 RouteAttrs::Gateway(val) => {
1059 if last_off == offset {
1060 stack.push(("Gateway", last_off));
1061 break;
1062 }
1063 }
1064 RouteAttrs::Priority(val) => {
1065 if last_off == offset {
1066 stack.push(("Priority", last_off));
1067 break;
1068 }
1069 }
1070 RouteAttrs::Prefsrc(val) => {
1071 if last_off == offset {
1072 stack.push(("Prefsrc", last_off));
1073 break;
1074 }
1075 }
1076 RouteAttrs::Metrics(val) => {
1077 (stack, missing) = val.lookup_attr(offset, missing_type);
1078 if !stack.is_empty() {
1079 break;
1080 }
1081 }
1082 RouteAttrs::Multipath(val) => {
1083 if last_off == offset {
1084 stack.push(("Multipath", last_off));
1085 break;
1086 }
1087 }
1088 RouteAttrs::Protoinfo(val) => {
1089 if last_off == offset {
1090 stack.push(("Protoinfo", last_off));
1091 break;
1092 }
1093 }
1094 RouteAttrs::Flow(val) => {
1095 if last_off == offset {
1096 stack.push(("Flow", last_off));
1097 break;
1098 }
1099 }
1100 RouteAttrs::Cacheinfo(val) => {
1101 if last_off == offset {
1102 stack.push(("Cacheinfo", last_off));
1103 break;
1104 }
1105 }
1106 RouteAttrs::Session(val) => {
1107 if last_off == offset {
1108 stack.push(("Session", last_off));
1109 break;
1110 }
1111 }
1112 RouteAttrs::MpAlgo(val) => {
1113 if last_off == offset {
1114 stack.push(("MpAlgo", last_off));
1115 break;
1116 }
1117 }
1118 RouteAttrs::Table(val) => {
1119 if last_off == offset {
1120 stack.push(("Table", last_off));
1121 break;
1122 }
1123 }
1124 RouteAttrs::Mark(val) => {
1125 if last_off == offset {
1126 stack.push(("Mark", last_off));
1127 break;
1128 }
1129 }
1130 RouteAttrs::MfcStats(val) => {
1131 if last_off == offset {
1132 stack.push(("MfcStats", last_off));
1133 break;
1134 }
1135 }
1136 RouteAttrs::Via(val) => {
1137 if last_off == offset {
1138 stack.push(("Via", last_off));
1139 break;
1140 }
1141 }
1142 RouteAttrs::Newdst(val) => {
1143 if last_off == offset {
1144 stack.push(("Newdst", last_off));
1145 break;
1146 }
1147 }
1148 RouteAttrs::Pref(val) => {
1149 if last_off == offset {
1150 stack.push(("Pref", last_off));
1151 break;
1152 }
1153 }
1154 RouteAttrs::EncapType(val) => {
1155 if last_off == offset {
1156 stack.push(("EncapType", last_off));
1157 break;
1158 }
1159 }
1160 RouteAttrs::Encap(val) => {
1161 if last_off == offset {
1162 stack.push(("Encap", last_off));
1163 break;
1164 }
1165 }
1166 RouteAttrs::Expires(val) => {
1167 if last_off == offset {
1168 stack.push(("Expires", last_off));
1169 break;
1170 }
1171 }
1172 RouteAttrs::Pad(val) => {
1173 if last_off == offset {
1174 stack.push(("Pad", last_off));
1175 break;
1176 }
1177 }
1178 RouteAttrs::Uid(val) => {
1179 if last_off == offset {
1180 stack.push(("Uid", last_off));
1181 break;
1182 }
1183 }
1184 RouteAttrs::TtlPropagate(val) => {
1185 if last_off == offset {
1186 stack.push(("TtlPropagate", last_off));
1187 break;
1188 }
1189 }
1190 RouteAttrs::IpProto(val) => {
1191 if last_off == offset {
1192 stack.push(("IpProto", last_off));
1193 break;
1194 }
1195 }
1196 RouteAttrs::Sport(val) => {
1197 if last_off == offset {
1198 stack.push(("Sport", last_off));
1199 break;
1200 }
1201 }
1202 RouteAttrs::Dport(val) => {
1203 if last_off == offset {
1204 stack.push(("Dport", last_off));
1205 break;
1206 }
1207 }
1208 RouteAttrs::NhId(val) => {
1209 if last_off == offset {
1210 stack.push(("NhId", last_off));
1211 break;
1212 }
1213 }
1214 RouteAttrs::Flowlabel(val) => {
1215 if last_off == offset {
1216 stack.push(("Flowlabel", last_off));
1217 break;
1218 }
1219 }
1220 _ => {}
1221 };
1222 last_off = cur + attrs.pos;
1223 }
1224 if !stack.is_empty() {
1225 stack.push(("RouteAttrs", cur));
1226 }
1227 (stack, missing)
1228 }
1229}
1230#[derive(Clone)]
1231pub enum Metrics<'a> {
1232 Lock(u32),
1233 Mtu(u32),
1234 Window(u32),
1235 Rtt(u32),
1236 Rttvar(u32),
1237 Ssthresh(u32),
1238 Cwnd(u32),
1239 Advmss(u32),
1240 Reordering(u32),
1241 Hoplimit(u32),
1242 Initcwnd(u32),
1243 Features(u32),
1244 RtoMin(u32),
1245 Initrwnd(u32),
1246 Quickack(u32),
1247 CcAlgo(&'a CStr),
1248 FastopenNoCookie(u32),
1249}
1250impl<'a> IterableMetrics<'a> {
1251 pub fn get_lock(&self) -> Result<u32, ErrorContext> {
1252 let mut iter = self.clone();
1253 iter.pos = 0;
1254 for attr in iter {
1255 if let Metrics::Lock(val) = attr? {
1256 return Ok(val);
1257 }
1258 }
1259 Err(ErrorContext::new_missing(
1260 "Metrics",
1261 "Lock",
1262 self.orig_loc,
1263 self.buf.as_ptr() as usize,
1264 ))
1265 }
1266 pub fn get_mtu(&self) -> Result<u32, ErrorContext> {
1267 let mut iter = self.clone();
1268 iter.pos = 0;
1269 for attr in iter {
1270 if let Metrics::Mtu(val) = attr? {
1271 return Ok(val);
1272 }
1273 }
1274 Err(ErrorContext::new_missing(
1275 "Metrics",
1276 "Mtu",
1277 self.orig_loc,
1278 self.buf.as_ptr() as usize,
1279 ))
1280 }
1281 pub fn get_window(&self) -> Result<u32, ErrorContext> {
1282 let mut iter = self.clone();
1283 iter.pos = 0;
1284 for attr in iter {
1285 if let Metrics::Window(val) = attr? {
1286 return Ok(val);
1287 }
1288 }
1289 Err(ErrorContext::new_missing(
1290 "Metrics",
1291 "Window",
1292 self.orig_loc,
1293 self.buf.as_ptr() as usize,
1294 ))
1295 }
1296 pub fn get_rtt(&self) -> Result<u32, ErrorContext> {
1297 let mut iter = self.clone();
1298 iter.pos = 0;
1299 for attr in iter {
1300 if let Metrics::Rtt(val) = attr? {
1301 return Ok(val);
1302 }
1303 }
1304 Err(ErrorContext::new_missing(
1305 "Metrics",
1306 "Rtt",
1307 self.orig_loc,
1308 self.buf.as_ptr() as usize,
1309 ))
1310 }
1311 pub fn get_rttvar(&self) -> Result<u32, ErrorContext> {
1312 let mut iter = self.clone();
1313 iter.pos = 0;
1314 for attr in iter {
1315 if let Metrics::Rttvar(val) = attr? {
1316 return Ok(val);
1317 }
1318 }
1319 Err(ErrorContext::new_missing(
1320 "Metrics",
1321 "Rttvar",
1322 self.orig_loc,
1323 self.buf.as_ptr() as usize,
1324 ))
1325 }
1326 pub fn get_ssthresh(&self) -> Result<u32, ErrorContext> {
1327 let mut iter = self.clone();
1328 iter.pos = 0;
1329 for attr in iter {
1330 if let Metrics::Ssthresh(val) = attr? {
1331 return Ok(val);
1332 }
1333 }
1334 Err(ErrorContext::new_missing(
1335 "Metrics",
1336 "Ssthresh",
1337 self.orig_loc,
1338 self.buf.as_ptr() as usize,
1339 ))
1340 }
1341 pub fn get_cwnd(&self) -> Result<u32, ErrorContext> {
1342 let mut iter = self.clone();
1343 iter.pos = 0;
1344 for attr in iter {
1345 if let Metrics::Cwnd(val) = attr? {
1346 return Ok(val);
1347 }
1348 }
1349 Err(ErrorContext::new_missing(
1350 "Metrics",
1351 "Cwnd",
1352 self.orig_loc,
1353 self.buf.as_ptr() as usize,
1354 ))
1355 }
1356 pub fn get_advmss(&self) -> Result<u32, ErrorContext> {
1357 let mut iter = self.clone();
1358 iter.pos = 0;
1359 for attr in iter {
1360 if let Metrics::Advmss(val) = attr? {
1361 return Ok(val);
1362 }
1363 }
1364 Err(ErrorContext::new_missing(
1365 "Metrics",
1366 "Advmss",
1367 self.orig_loc,
1368 self.buf.as_ptr() as usize,
1369 ))
1370 }
1371 pub fn get_reordering(&self) -> Result<u32, ErrorContext> {
1372 let mut iter = self.clone();
1373 iter.pos = 0;
1374 for attr in iter {
1375 if let Metrics::Reordering(val) = attr? {
1376 return Ok(val);
1377 }
1378 }
1379 Err(ErrorContext::new_missing(
1380 "Metrics",
1381 "Reordering",
1382 self.orig_loc,
1383 self.buf.as_ptr() as usize,
1384 ))
1385 }
1386 pub fn get_hoplimit(&self) -> Result<u32, ErrorContext> {
1387 let mut iter = self.clone();
1388 iter.pos = 0;
1389 for attr in iter {
1390 if let Metrics::Hoplimit(val) = attr? {
1391 return Ok(val);
1392 }
1393 }
1394 Err(ErrorContext::new_missing(
1395 "Metrics",
1396 "Hoplimit",
1397 self.orig_loc,
1398 self.buf.as_ptr() as usize,
1399 ))
1400 }
1401 pub fn get_initcwnd(&self) -> Result<u32, ErrorContext> {
1402 let mut iter = self.clone();
1403 iter.pos = 0;
1404 for attr in iter {
1405 if let Metrics::Initcwnd(val) = attr? {
1406 return Ok(val);
1407 }
1408 }
1409 Err(ErrorContext::new_missing(
1410 "Metrics",
1411 "Initcwnd",
1412 self.orig_loc,
1413 self.buf.as_ptr() as usize,
1414 ))
1415 }
1416 pub fn get_features(&self) -> Result<u32, ErrorContext> {
1417 let mut iter = self.clone();
1418 iter.pos = 0;
1419 for attr in iter {
1420 if let Metrics::Features(val) = attr? {
1421 return Ok(val);
1422 }
1423 }
1424 Err(ErrorContext::new_missing(
1425 "Metrics",
1426 "Features",
1427 self.orig_loc,
1428 self.buf.as_ptr() as usize,
1429 ))
1430 }
1431 pub fn get_rto_min(&self) -> Result<u32, ErrorContext> {
1432 let mut iter = self.clone();
1433 iter.pos = 0;
1434 for attr in iter {
1435 if let Metrics::RtoMin(val) = attr? {
1436 return Ok(val);
1437 }
1438 }
1439 Err(ErrorContext::new_missing(
1440 "Metrics",
1441 "RtoMin",
1442 self.orig_loc,
1443 self.buf.as_ptr() as usize,
1444 ))
1445 }
1446 pub fn get_initrwnd(&self) -> Result<u32, ErrorContext> {
1447 let mut iter = self.clone();
1448 iter.pos = 0;
1449 for attr in iter {
1450 if let Metrics::Initrwnd(val) = attr? {
1451 return Ok(val);
1452 }
1453 }
1454 Err(ErrorContext::new_missing(
1455 "Metrics",
1456 "Initrwnd",
1457 self.orig_loc,
1458 self.buf.as_ptr() as usize,
1459 ))
1460 }
1461 pub fn get_quickack(&self) -> Result<u32, ErrorContext> {
1462 let mut iter = self.clone();
1463 iter.pos = 0;
1464 for attr in iter {
1465 if let Metrics::Quickack(val) = attr? {
1466 return Ok(val);
1467 }
1468 }
1469 Err(ErrorContext::new_missing(
1470 "Metrics",
1471 "Quickack",
1472 self.orig_loc,
1473 self.buf.as_ptr() as usize,
1474 ))
1475 }
1476 pub fn get_cc_algo(&self) -> Result<&'a CStr, ErrorContext> {
1477 let mut iter = self.clone();
1478 iter.pos = 0;
1479 for attr in iter {
1480 if let Metrics::CcAlgo(val) = attr? {
1481 return Ok(val);
1482 }
1483 }
1484 Err(ErrorContext::new_missing(
1485 "Metrics",
1486 "CcAlgo",
1487 self.orig_loc,
1488 self.buf.as_ptr() as usize,
1489 ))
1490 }
1491 pub fn get_fastopen_no_cookie(&self) -> Result<u32, ErrorContext> {
1492 let mut iter = self.clone();
1493 iter.pos = 0;
1494 for attr in iter {
1495 if let Metrics::FastopenNoCookie(val) = attr? {
1496 return Ok(val);
1497 }
1498 }
1499 Err(ErrorContext::new_missing(
1500 "Metrics",
1501 "FastopenNoCookie",
1502 self.orig_loc,
1503 self.buf.as_ptr() as usize,
1504 ))
1505 }
1506}
1507impl Metrics<'_> {
1508 pub fn new<'a>(buf: &'a [u8]) -> IterableMetrics<'a> {
1509 IterableMetrics::with_loc(buf, buf.as_ptr() as usize)
1510 }
1511 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1512 let res = match r#type {
1513 0u16 => "Unspec",
1514 1u16 => "Lock",
1515 2u16 => "Mtu",
1516 3u16 => "Window",
1517 4u16 => "Rtt",
1518 5u16 => "Rttvar",
1519 6u16 => "Ssthresh",
1520 7u16 => "Cwnd",
1521 8u16 => "Advmss",
1522 9u16 => "Reordering",
1523 10u16 => "Hoplimit",
1524 11u16 => "Initcwnd",
1525 12u16 => "Features",
1526 13u16 => "RtoMin",
1527 14u16 => "Initrwnd",
1528 15u16 => "Quickack",
1529 16u16 => "CcAlgo",
1530 17u16 => "FastopenNoCookie",
1531 _ => return None,
1532 };
1533 Some(res)
1534 }
1535}
1536#[derive(Clone, Copy, Default)]
1537pub struct IterableMetrics<'a> {
1538 buf: &'a [u8],
1539 pos: usize,
1540 orig_loc: usize,
1541}
1542impl<'a> IterableMetrics<'a> {
1543 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1544 Self {
1545 buf,
1546 pos: 0,
1547 orig_loc,
1548 }
1549 }
1550 pub fn get_buf(&self) -> &'a [u8] {
1551 self.buf
1552 }
1553}
1554impl<'a> Iterator for IterableMetrics<'a> {
1555 type Item = Result<Metrics<'a>, ErrorContext>;
1556 fn next(&mut self) -> Option<Self::Item> {
1557 let pos = self.pos;
1558 let mut r#type;
1559 loop {
1560 r#type = None;
1561 if self.buf.len() == self.pos {
1562 return None;
1563 }
1564 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1565 break;
1566 };
1567 r#type = Some(header.r#type);
1568 let res = match header.r#type {
1569 1u16 => Metrics::Lock({
1570 let res = parse_u32(next);
1571 let Some(val) = res else { break };
1572 val
1573 }),
1574 2u16 => Metrics::Mtu({
1575 let res = parse_u32(next);
1576 let Some(val) = res else { break };
1577 val
1578 }),
1579 3u16 => Metrics::Window({
1580 let res = parse_u32(next);
1581 let Some(val) = res else { break };
1582 val
1583 }),
1584 4u16 => Metrics::Rtt({
1585 let res = parse_u32(next);
1586 let Some(val) = res else { break };
1587 val
1588 }),
1589 5u16 => Metrics::Rttvar({
1590 let res = parse_u32(next);
1591 let Some(val) = res else { break };
1592 val
1593 }),
1594 6u16 => Metrics::Ssthresh({
1595 let res = parse_u32(next);
1596 let Some(val) = res else { break };
1597 val
1598 }),
1599 7u16 => Metrics::Cwnd({
1600 let res = parse_u32(next);
1601 let Some(val) = res else { break };
1602 val
1603 }),
1604 8u16 => Metrics::Advmss({
1605 let res = parse_u32(next);
1606 let Some(val) = res else { break };
1607 val
1608 }),
1609 9u16 => Metrics::Reordering({
1610 let res = parse_u32(next);
1611 let Some(val) = res else { break };
1612 val
1613 }),
1614 10u16 => Metrics::Hoplimit({
1615 let res = parse_u32(next);
1616 let Some(val) = res else { break };
1617 val
1618 }),
1619 11u16 => Metrics::Initcwnd({
1620 let res = parse_u32(next);
1621 let Some(val) = res else { break };
1622 val
1623 }),
1624 12u16 => Metrics::Features({
1625 let res = parse_u32(next);
1626 let Some(val) = res else { break };
1627 val
1628 }),
1629 13u16 => Metrics::RtoMin({
1630 let res = parse_u32(next);
1631 let Some(val) = res else { break };
1632 val
1633 }),
1634 14u16 => Metrics::Initrwnd({
1635 let res = parse_u32(next);
1636 let Some(val) = res else { break };
1637 val
1638 }),
1639 15u16 => Metrics::Quickack({
1640 let res = parse_u32(next);
1641 let Some(val) = res else { break };
1642 val
1643 }),
1644 16u16 => Metrics::CcAlgo({
1645 let res = CStr::from_bytes_with_nul(next).ok();
1646 let Some(val) = res else { break };
1647 val
1648 }),
1649 17u16 => Metrics::FastopenNoCookie({
1650 let res = parse_u32(next);
1651 let Some(val) = res else { break };
1652 val
1653 }),
1654 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1655 n => continue,
1656 };
1657 return Some(Ok(res));
1658 }
1659 Some(Err(ErrorContext::new(
1660 "Metrics",
1661 r#type.and_then(|t| Metrics::attr_from_type(t)),
1662 self.orig_loc,
1663 self.buf.as_ptr().wrapping_add(pos) as usize,
1664 )))
1665 }
1666}
1667impl<'a> std::fmt::Debug for IterableMetrics<'_> {
1668 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1669 let mut fmt = f.debug_struct("Metrics");
1670 for attr in self.clone() {
1671 let attr = match attr {
1672 Ok(a) => a,
1673 Err(err) => {
1674 fmt.finish()?;
1675 f.write_str("Err(")?;
1676 err.fmt(f)?;
1677 return f.write_str(")");
1678 }
1679 };
1680 match attr {
1681 Metrics::Lock(val) => fmt.field("Lock", &val),
1682 Metrics::Mtu(val) => fmt.field("Mtu", &val),
1683 Metrics::Window(val) => fmt.field("Window", &val),
1684 Metrics::Rtt(val) => fmt.field("Rtt", &val),
1685 Metrics::Rttvar(val) => fmt.field("Rttvar", &val),
1686 Metrics::Ssthresh(val) => fmt.field("Ssthresh", &val),
1687 Metrics::Cwnd(val) => fmt.field("Cwnd", &val),
1688 Metrics::Advmss(val) => fmt.field("Advmss", &val),
1689 Metrics::Reordering(val) => fmt.field("Reordering", &val),
1690 Metrics::Hoplimit(val) => fmt.field("Hoplimit", &val),
1691 Metrics::Initcwnd(val) => fmt.field("Initcwnd", &val),
1692 Metrics::Features(val) => fmt.field("Features", &val),
1693 Metrics::RtoMin(val) => fmt.field("RtoMin", &val),
1694 Metrics::Initrwnd(val) => fmt.field("Initrwnd", &val),
1695 Metrics::Quickack(val) => fmt.field("Quickack", &val),
1696 Metrics::CcAlgo(val) => fmt.field("CcAlgo", &val),
1697 Metrics::FastopenNoCookie(val) => fmt.field("FastopenNoCookie", &val),
1698 };
1699 }
1700 fmt.finish()
1701 }
1702}
1703impl IterableMetrics<'_> {
1704 pub fn lookup_attr(
1705 &self,
1706 offset: usize,
1707 missing_type: Option<u16>,
1708 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1709 let mut stack = Vec::new();
1710 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1711 if missing_type.is_some() && cur == offset {
1712 stack.push(("Metrics", offset));
1713 return (stack, missing_type.and_then(|t| Metrics::attr_from_type(t)));
1714 }
1715 if cur > offset || cur + self.buf.len() < offset {
1716 return (stack, None);
1717 }
1718 let mut attrs = self.clone();
1719 let mut last_off = cur + attrs.pos;
1720 while let Some(attr) = attrs.next() {
1721 let Ok(attr) = attr else { break };
1722 match attr {
1723 Metrics::Lock(val) => {
1724 if last_off == offset {
1725 stack.push(("Lock", last_off));
1726 break;
1727 }
1728 }
1729 Metrics::Mtu(val) => {
1730 if last_off == offset {
1731 stack.push(("Mtu", last_off));
1732 break;
1733 }
1734 }
1735 Metrics::Window(val) => {
1736 if last_off == offset {
1737 stack.push(("Window", last_off));
1738 break;
1739 }
1740 }
1741 Metrics::Rtt(val) => {
1742 if last_off == offset {
1743 stack.push(("Rtt", last_off));
1744 break;
1745 }
1746 }
1747 Metrics::Rttvar(val) => {
1748 if last_off == offset {
1749 stack.push(("Rttvar", last_off));
1750 break;
1751 }
1752 }
1753 Metrics::Ssthresh(val) => {
1754 if last_off == offset {
1755 stack.push(("Ssthresh", last_off));
1756 break;
1757 }
1758 }
1759 Metrics::Cwnd(val) => {
1760 if last_off == offset {
1761 stack.push(("Cwnd", last_off));
1762 break;
1763 }
1764 }
1765 Metrics::Advmss(val) => {
1766 if last_off == offset {
1767 stack.push(("Advmss", last_off));
1768 break;
1769 }
1770 }
1771 Metrics::Reordering(val) => {
1772 if last_off == offset {
1773 stack.push(("Reordering", last_off));
1774 break;
1775 }
1776 }
1777 Metrics::Hoplimit(val) => {
1778 if last_off == offset {
1779 stack.push(("Hoplimit", last_off));
1780 break;
1781 }
1782 }
1783 Metrics::Initcwnd(val) => {
1784 if last_off == offset {
1785 stack.push(("Initcwnd", last_off));
1786 break;
1787 }
1788 }
1789 Metrics::Features(val) => {
1790 if last_off == offset {
1791 stack.push(("Features", last_off));
1792 break;
1793 }
1794 }
1795 Metrics::RtoMin(val) => {
1796 if last_off == offset {
1797 stack.push(("RtoMin", last_off));
1798 break;
1799 }
1800 }
1801 Metrics::Initrwnd(val) => {
1802 if last_off == offset {
1803 stack.push(("Initrwnd", last_off));
1804 break;
1805 }
1806 }
1807 Metrics::Quickack(val) => {
1808 if last_off == offset {
1809 stack.push(("Quickack", last_off));
1810 break;
1811 }
1812 }
1813 Metrics::CcAlgo(val) => {
1814 if last_off == offset {
1815 stack.push(("CcAlgo", last_off));
1816 break;
1817 }
1818 }
1819 Metrics::FastopenNoCookie(val) => {
1820 if last_off == offset {
1821 stack.push(("FastopenNoCookie", last_off));
1822 break;
1823 }
1824 }
1825 _ => {}
1826 };
1827 last_off = cur + attrs.pos;
1828 }
1829 if !stack.is_empty() {
1830 stack.push(("Metrics", cur));
1831 }
1832 (stack, None)
1833 }
1834}
1835pub struct PushRouteAttrs<Prev: Rec> {
1836 pub(crate) prev: Option<Prev>,
1837 pub(crate) header_offset: Option<usize>,
1838}
1839impl<Prev: Rec> Rec for PushRouteAttrs<Prev> {
1840 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1841 self.prev.as_mut().unwrap().as_rec_mut()
1842 }
1843 fn as_rec(&self) -> &Vec<u8> {
1844 self.prev.as_ref().unwrap().as_rec()
1845 }
1846}
1847impl<Prev: Rec> PushRouteAttrs<Prev> {
1848 pub fn new(prev: Prev) -> Self {
1849 Self {
1850 prev: Some(prev),
1851 header_offset: None,
1852 }
1853 }
1854 pub fn end_nested(mut self) -> Prev {
1855 let mut prev = self.prev.take().unwrap();
1856 if let Some(header_offset) = &self.header_offset {
1857 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1858 }
1859 prev
1860 }
1861 pub fn push_dst(mut self, value: std::net::IpAddr) -> Self {
1862 push_header(self.as_rec_mut(), 1u16, {
1863 match &value {
1864 IpAddr::V4(_) => 4,
1865 IpAddr::V6(_) => 16,
1866 }
1867 } as u16);
1868 encode_ip(self.as_rec_mut(), value);
1869 self
1870 }
1871 pub fn push_src(mut self, value: std::net::IpAddr) -> Self {
1872 push_header(self.as_rec_mut(), 2u16, {
1873 match &value {
1874 IpAddr::V4(_) => 4,
1875 IpAddr::V6(_) => 16,
1876 }
1877 } as u16);
1878 encode_ip(self.as_rec_mut(), value);
1879 self
1880 }
1881 pub fn push_iif(mut self, value: u32) -> Self {
1882 push_header(self.as_rec_mut(), 3u16, 4 as u16);
1883 self.as_rec_mut().extend(value.to_ne_bytes());
1884 self
1885 }
1886 pub fn push_oif(mut self, value: u32) -> Self {
1887 push_header(self.as_rec_mut(), 4u16, 4 as u16);
1888 self.as_rec_mut().extend(value.to_ne_bytes());
1889 self
1890 }
1891 pub fn push_gateway(mut self, value: std::net::IpAddr) -> Self {
1892 push_header(self.as_rec_mut(), 5u16, {
1893 match &value {
1894 IpAddr::V4(_) => 4,
1895 IpAddr::V6(_) => 16,
1896 }
1897 } as u16);
1898 encode_ip(self.as_rec_mut(), value);
1899 self
1900 }
1901 pub fn push_priority(mut self, value: u32) -> Self {
1902 push_header(self.as_rec_mut(), 6u16, 4 as u16);
1903 self.as_rec_mut().extend(value.to_ne_bytes());
1904 self
1905 }
1906 pub fn push_prefsrc(mut self, value: std::net::IpAddr) -> Self {
1907 push_header(self.as_rec_mut(), 7u16, {
1908 match &value {
1909 IpAddr::V4(_) => 4,
1910 IpAddr::V6(_) => 16,
1911 }
1912 } as u16);
1913 encode_ip(self.as_rec_mut(), value);
1914 self
1915 }
1916 pub fn nested_metrics(mut self) -> PushMetrics<Self> {
1917 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1918 PushMetrics {
1919 prev: Some(self),
1920 header_offset: Some(header_offset),
1921 }
1922 }
1923 pub fn push_multipath(mut self, value: &[u8]) -> Self {
1924 push_header(self.as_rec_mut(), 9u16, value.len() as u16);
1925 self.as_rec_mut().extend(value);
1926 self
1927 }
1928 pub fn push_protoinfo(mut self, value: &[u8]) -> Self {
1929 push_header(self.as_rec_mut(), 10u16, value.len() as u16);
1930 self.as_rec_mut().extend(value);
1931 self
1932 }
1933 pub fn push_flow(mut self, value: u32) -> Self {
1934 push_header(self.as_rec_mut(), 11u16, 4 as u16);
1935 self.as_rec_mut().extend(value.to_ne_bytes());
1936 self
1937 }
1938 pub fn push_cacheinfo(mut self, value: RtaCacheinfo) -> Self {
1939 push_header(self.as_rec_mut(), 12u16, value.as_slice().len() as u16);
1940 self.as_rec_mut().extend(value.as_slice());
1941 self
1942 }
1943 pub fn push_session(mut self, value: &[u8]) -> Self {
1944 push_header(self.as_rec_mut(), 13u16, value.len() as u16);
1945 self.as_rec_mut().extend(value);
1946 self
1947 }
1948 pub fn push_mp_algo(mut self, value: &[u8]) -> Self {
1949 push_header(self.as_rec_mut(), 14u16, value.len() as u16);
1950 self.as_rec_mut().extend(value);
1951 self
1952 }
1953 pub fn push_table(mut self, value: u32) -> Self {
1954 push_header(self.as_rec_mut(), 15u16, 4 as u16);
1955 self.as_rec_mut().extend(value.to_ne_bytes());
1956 self
1957 }
1958 pub fn push_mark(mut self, value: u32) -> Self {
1959 push_header(self.as_rec_mut(), 16u16, 4 as u16);
1960 self.as_rec_mut().extend(value.to_ne_bytes());
1961 self
1962 }
1963 pub fn push_mfc_stats(mut self, value: &[u8]) -> Self {
1964 push_header(self.as_rec_mut(), 17u16, value.len() as u16);
1965 self.as_rec_mut().extend(value);
1966 self
1967 }
1968 pub fn push_via(mut self, value: &[u8]) -> Self {
1969 push_header(self.as_rec_mut(), 18u16, value.len() as u16);
1970 self.as_rec_mut().extend(value);
1971 self
1972 }
1973 pub fn push_newdst(mut self, value: &[u8]) -> Self {
1974 push_header(self.as_rec_mut(), 19u16, value.len() as u16);
1975 self.as_rec_mut().extend(value);
1976 self
1977 }
1978 pub fn push_pref(mut self, value: u8) -> Self {
1979 push_header(self.as_rec_mut(), 20u16, 1 as u16);
1980 self.as_rec_mut().extend(value.to_ne_bytes());
1981 self
1982 }
1983 pub fn push_encap_type(mut self, value: u16) -> Self {
1984 push_header(self.as_rec_mut(), 21u16, 2 as u16);
1985 self.as_rec_mut().extend(value.to_ne_bytes());
1986 self
1987 }
1988 pub fn push_encap(mut self, value: &[u8]) -> Self {
1989 push_header(self.as_rec_mut(), 22u16, value.len() as u16);
1990 self.as_rec_mut().extend(value);
1991 self
1992 }
1993 pub fn push_expires(mut self, value: u32) -> Self {
1994 push_header(self.as_rec_mut(), 23u16, 4 as u16);
1995 self.as_rec_mut().extend(value.to_ne_bytes());
1996 self
1997 }
1998 pub fn push_pad(mut self, value: &[u8]) -> Self {
1999 push_header(self.as_rec_mut(), 24u16, value.len() as u16);
2000 self.as_rec_mut().extend(value);
2001 self
2002 }
2003 pub fn push_uid(mut self, value: u32) -> Self {
2004 push_header(self.as_rec_mut(), 25u16, 4 as u16);
2005 self.as_rec_mut().extend(value.to_ne_bytes());
2006 self
2007 }
2008 pub fn push_ttl_propagate(mut self, value: u8) -> Self {
2009 push_header(self.as_rec_mut(), 26u16, 1 as u16);
2010 self.as_rec_mut().extend(value.to_ne_bytes());
2011 self
2012 }
2013 pub fn push_ip_proto(mut self, value: u8) -> Self {
2014 push_header(self.as_rec_mut(), 27u16, 1 as u16);
2015 self.as_rec_mut().extend(value.to_ne_bytes());
2016 self
2017 }
2018 pub fn push_sport(mut self, value: u16) -> Self {
2019 push_header(self.as_rec_mut(), 28u16, 2 as u16);
2020 self.as_rec_mut().extend(value.to_ne_bytes());
2021 self
2022 }
2023 pub fn push_dport(mut self, value: u16) -> Self {
2024 push_header(self.as_rec_mut(), 29u16, 2 as u16);
2025 self.as_rec_mut().extend(value.to_ne_bytes());
2026 self
2027 }
2028 pub fn push_nh_id(mut self, value: u32) -> Self {
2029 push_header(self.as_rec_mut(), 30u16, 4 as u16);
2030 self.as_rec_mut().extend(value.to_ne_bytes());
2031 self
2032 }
2033 pub fn push_flowlabel(mut self, value: u32) -> Self {
2034 push_header(self.as_rec_mut(), 31u16, 4 as u16);
2035 self.as_rec_mut().extend(value.to_be_bytes());
2036 self
2037 }
2038}
2039impl<Prev: Rec> Drop for PushRouteAttrs<Prev> {
2040 fn drop(&mut self) {
2041 if let Some(prev) = &mut self.prev {
2042 if let Some(header_offset) = &self.header_offset {
2043 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2044 }
2045 }
2046 }
2047}
2048pub struct PushMetrics<Prev: Rec> {
2049 pub(crate) prev: Option<Prev>,
2050 pub(crate) header_offset: Option<usize>,
2051}
2052impl<Prev: Rec> Rec for PushMetrics<Prev> {
2053 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2054 self.prev.as_mut().unwrap().as_rec_mut()
2055 }
2056 fn as_rec(&self) -> &Vec<u8> {
2057 self.prev.as_ref().unwrap().as_rec()
2058 }
2059}
2060impl<Prev: Rec> PushMetrics<Prev> {
2061 pub fn new(prev: Prev) -> Self {
2062 Self {
2063 prev: Some(prev),
2064 header_offset: None,
2065 }
2066 }
2067 pub fn end_nested(mut self) -> Prev {
2068 let mut prev = self.prev.take().unwrap();
2069 if let Some(header_offset) = &self.header_offset {
2070 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2071 }
2072 prev
2073 }
2074 pub fn push_lock(mut self, value: u32) -> Self {
2075 push_header(self.as_rec_mut(), 1u16, 4 as u16);
2076 self.as_rec_mut().extend(value.to_ne_bytes());
2077 self
2078 }
2079 pub fn push_mtu(mut self, value: u32) -> Self {
2080 push_header(self.as_rec_mut(), 2u16, 4 as u16);
2081 self.as_rec_mut().extend(value.to_ne_bytes());
2082 self
2083 }
2084 pub fn push_window(mut self, value: u32) -> Self {
2085 push_header(self.as_rec_mut(), 3u16, 4 as u16);
2086 self.as_rec_mut().extend(value.to_ne_bytes());
2087 self
2088 }
2089 pub fn push_rtt(mut self, value: u32) -> Self {
2090 push_header(self.as_rec_mut(), 4u16, 4 as u16);
2091 self.as_rec_mut().extend(value.to_ne_bytes());
2092 self
2093 }
2094 pub fn push_rttvar(mut self, value: u32) -> Self {
2095 push_header(self.as_rec_mut(), 5u16, 4 as u16);
2096 self.as_rec_mut().extend(value.to_ne_bytes());
2097 self
2098 }
2099 pub fn push_ssthresh(mut self, value: u32) -> Self {
2100 push_header(self.as_rec_mut(), 6u16, 4 as u16);
2101 self.as_rec_mut().extend(value.to_ne_bytes());
2102 self
2103 }
2104 pub fn push_cwnd(mut self, value: u32) -> Self {
2105 push_header(self.as_rec_mut(), 7u16, 4 as u16);
2106 self.as_rec_mut().extend(value.to_ne_bytes());
2107 self
2108 }
2109 pub fn push_advmss(mut self, value: u32) -> Self {
2110 push_header(self.as_rec_mut(), 8u16, 4 as u16);
2111 self.as_rec_mut().extend(value.to_ne_bytes());
2112 self
2113 }
2114 pub fn push_reordering(mut self, value: u32) -> Self {
2115 push_header(self.as_rec_mut(), 9u16, 4 as u16);
2116 self.as_rec_mut().extend(value.to_ne_bytes());
2117 self
2118 }
2119 pub fn push_hoplimit(mut self, value: u32) -> Self {
2120 push_header(self.as_rec_mut(), 10u16, 4 as u16);
2121 self.as_rec_mut().extend(value.to_ne_bytes());
2122 self
2123 }
2124 pub fn push_initcwnd(mut self, value: u32) -> Self {
2125 push_header(self.as_rec_mut(), 11u16, 4 as u16);
2126 self.as_rec_mut().extend(value.to_ne_bytes());
2127 self
2128 }
2129 pub fn push_features(mut self, value: u32) -> Self {
2130 push_header(self.as_rec_mut(), 12u16, 4 as u16);
2131 self.as_rec_mut().extend(value.to_ne_bytes());
2132 self
2133 }
2134 pub fn push_rto_min(mut self, value: u32) -> Self {
2135 push_header(self.as_rec_mut(), 13u16, 4 as u16);
2136 self.as_rec_mut().extend(value.to_ne_bytes());
2137 self
2138 }
2139 pub fn push_initrwnd(mut self, value: u32) -> Self {
2140 push_header(self.as_rec_mut(), 14u16, 4 as u16);
2141 self.as_rec_mut().extend(value.to_ne_bytes());
2142 self
2143 }
2144 pub fn push_quickack(mut self, value: u32) -> Self {
2145 push_header(self.as_rec_mut(), 15u16, 4 as u16);
2146 self.as_rec_mut().extend(value.to_ne_bytes());
2147 self
2148 }
2149 pub fn push_cc_algo(mut self, value: &CStr) -> Self {
2150 push_header(
2151 self.as_rec_mut(),
2152 16u16,
2153 value.to_bytes_with_nul().len() as u16,
2154 );
2155 self.as_rec_mut().extend(value.to_bytes_with_nul());
2156 self
2157 }
2158 pub fn push_cc_algo_bytes(mut self, value: &[u8]) -> Self {
2159 push_header(self.as_rec_mut(), 16u16, (value.len() + 1) as u16);
2160 self.as_rec_mut().extend(value);
2161 self.as_rec_mut().push(0);
2162 self
2163 }
2164 pub fn push_fastopen_no_cookie(mut self, value: u32) -> Self {
2165 push_header(self.as_rec_mut(), 17u16, 4 as u16);
2166 self.as_rec_mut().extend(value.to_ne_bytes());
2167 self
2168 }
2169}
2170impl<Prev: Rec> Drop for PushMetrics<Prev> {
2171 fn drop(&mut self) {
2172 if let Some(prev) = &mut self.prev {
2173 if let Some(header_offset) = &self.header_offset {
2174 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2175 }
2176 }
2177 }
2178}
2179#[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"]
2180#[derive(Debug)]
2181pub struct OpGetrouteDump<'r> {
2182 request: Request<'r>,
2183}
2184impl<'r> OpGetrouteDump<'r> {
2185 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2186 Self::write_header(request.buf_mut(), header);
2187 Self {
2188 request: request.set_dump(),
2189 }
2190 }
2191 pub fn encode_request<'buf>(
2192 buf: &'buf mut Vec<u8>,
2193 header: &Rtmsg,
2194 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2195 Self::write_header(buf, header);
2196 PushRouteAttrs::new(buf)
2197 }
2198 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2199 PushRouteAttrs::new(self.request.buf_mut())
2200 }
2201 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2202 PushRouteAttrs::new(self.request.buf)
2203 }
2204 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2205 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2206 (
2207 Rtmsg::new_from_slice(header).unwrap_or_default(),
2208 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2209 )
2210 }
2211 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2212 prev.as_rec_mut().extend(header.as_slice());
2213 }
2214}
2215impl NetlinkRequest for OpGetrouteDump<'_> {
2216 fn protocol(&self) -> Protocol {
2217 Protocol::Raw {
2218 protonum: 0u16,
2219 request_type: 26u16,
2220 }
2221 }
2222 fn flags(&self) -> u16 {
2223 self.request.flags
2224 }
2225 fn payload(&self) -> &[u8] {
2226 self.request.buf()
2227 }
2228 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2229 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2230 Self::decode_request(buf)
2231 }
2232 fn lookup(
2233 buf: &[u8],
2234 offset: usize,
2235 missing_type: Option<u16>,
2236 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2237 Self::decode_request(buf)
2238 .1
2239 .lookup_attr(offset, missing_type)
2240 }
2241}
2242#[doc = "Dump route information\\.\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"]
2243#[derive(Debug)]
2244pub struct OpGetrouteDo<'r> {
2245 request: Request<'r>,
2246}
2247impl<'r> OpGetrouteDo<'r> {
2248 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2249 Self::write_header(request.buf_mut(), header);
2250 Self { request: request }
2251 }
2252 pub fn encode_request<'buf>(
2253 buf: &'buf mut Vec<u8>,
2254 header: &Rtmsg,
2255 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2256 Self::write_header(buf, header);
2257 PushRouteAttrs::new(buf)
2258 }
2259 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2260 PushRouteAttrs::new(self.request.buf_mut())
2261 }
2262 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2263 PushRouteAttrs::new(self.request.buf)
2264 }
2265 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2266 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2267 (
2268 Rtmsg::new_from_slice(header).unwrap_or_default(),
2269 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2270 )
2271 }
2272 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2273 prev.as_rec_mut().extend(header.as_slice());
2274 }
2275}
2276impl NetlinkRequest for OpGetrouteDo<'_> {
2277 fn protocol(&self) -> Protocol {
2278 Protocol::Raw {
2279 protonum: 0u16,
2280 request_type: 26u16,
2281 }
2282 }
2283 fn flags(&self) -> u16 {
2284 self.request.flags
2285 }
2286 fn payload(&self) -> &[u8] {
2287 self.request.buf()
2288 }
2289 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2290 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2291 Self::decode_request(buf)
2292 }
2293 fn lookup(
2294 buf: &[u8],
2295 offset: usize,
2296 missing_type: Option<u16>,
2297 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2298 Self::decode_request(buf)
2299 .1
2300 .lookup_attr(offset, missing_type)
2301 }
2302}
2303#[doc = "Create a new route\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"]
2304#[derive(Debug)]
2305pub struct OpNewrouteDo<'r> {
2306 request: Request<'r>,
2307}
2308impl<'r> OpNewrouteDo<'r> {
2309 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2310 Self::write_header(request.buf_mut(), header);
2311 Self { request: request }
2312 }
2313 pub fn encode_request<'buf>(
2314 buf: &'buf mut Vec<u8>,
2315 header: &Rtmsg,
2316 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2317 Self::write_header(buf, header);
2318 PushRouteAttrs::new(buf)
2319 }
2320 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2321 PushRouteAttrs::new(self.request.buf_mut())
2322 }
2323 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2324 PushRouteAttrs::new(self.request.buf)
2325 }
2326 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2327 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2328 (
2329 Rtmsg::new_from_slice(header).unwrap_or_default(),
2330 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2331 )
2332 }
2333 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2334 prev.as_rec_mut().extend(header.as_slice());
2335 }
2336}
2337impl NetlinkRequest for OpNewrouteDo<'_> {
2338 fn protocol(&self) -> Protocol {
2339 Protocol::Raw {
2340 protonum: 0u16,
2341 request_type: 24u16,
2342 }
2343 }
2344 fn flags(&self) -> u16 {
2345 self.request.flags
2346 }
2347 fn payload(&self) -> &[u8] {
2348 self.request.buf()
2349 }
2350 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2351 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2352 Self::decode_request(buf)
2353 }
2354 fn lookup(
2355 buf: &[u8],
2356 offset: usize,
2357 missing_type: Option<u16>,
2358 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2359 Self::decode_request(buf)
2360 .1
2361 .lookup_attr(offset, missing_type)
2362 }
2363}
2364#[doc = "Delete an existing route\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"]
2365#[derive(Debug)]
2366pub struct OpDelrouteDo<'r> {
2367 request: Request<'r>,
2368}
2369impl<'r> OpDelrouteDo<'r> {
2370 pub fn new(mut request: Request<'r>, header: &Rtmsg) -> Self {
2371 Self::write_header(request.buf_mut(), header);
2372 Self { request: request }
2373 }
2374 pub fn encode_request<'buf>(
2375 buf: &'buf mut Vec<u8>,
2376 header: &Rtmsg,
2377 ) -> PushRouteAttrs<&'buf mut Vec<u8>> {
2378 Self::write_header(buf, header);
2379 PushRouteAttrs::new(buf)
2380 }
2381 pub fn encode(&mut self) -> PushRouteAttrs<&mut Vec<u8>> {
2382 PushRouteAttrs::new(self.request.buf_mut())
2383 }
2384 pub fn into_encoder(self) -> PushRouteAttrs<RequestBuf<'r>> {
2385 PushRouteAttrs::new(self.request.buf)
2386 }
2387 pub fn decode_request<'a>(buf: &'a [u8]) -> (Rtmsg, IterableRouteAttrs<'a>) {
2388 let (header, attrs) = buf.split_at(buf.len().min(Rtmsg::len()));
2389 (
2390 Rtmsg::new_from_slice(header).unwrap_or_default(),
2391 IterableRouteAttrs::with_loc(attrs, buf.as_ptr() as usize),
2392 )
2393 }
2394 fn write_header<Prev: Rec>(prev: &mut Prev, header: &Rtmsg) {
2395 prev.as_rec_mut().extend(header.as_slice());
2396 }
2397}
2398impl NetlinkRequest for OpDelrouteDo<'_> {
2399 fn protocol(&self) -> Protocol {
2400 Protocol::Raw {
2401 protonum: 0u16,
2402 request_type: 25u16,
2403 }
2404 }
2405 fn flags(&self) -> u16 {
2406 self.request.flags
2407 }
2408 fn payload(&self) -> &[u8] {
2409 self.request.buf()
2410 }
2411 type ReplyType<'buf> = (Rtmsg, IterableRouteAttrs<'buf>);
2412 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2413 Self::decode_request(buf)
2414 }
2415 fn lookup(
2416 buf: &[u8],
2417 offset: usize,
2418 missing_type: Option<u16>,
2419 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2420 Self::decode_request(buf)
2421 .1
2422 .lookup_attr(offset, missing_type)
2423 }
2424}
2425#[derive(Debug)]
2426pub struct ChainedFinal<'a> {
2427 inner: Chained<'a>,
2428}
2429#[derive(Debug)]
2430pub struct Chained<'a> {
2431 buf: RequestBuf<'a>,
2432 first_seq: u32,
2433 lookups: Vec<(&'static str, LookupFn)>,
2434 last_header_offset: usize,
2435 last_kind: Option<RequestInfo>,
2436}
2437impl<'a> ChainedFinal<'a> {
2438 pub fn into_chained(self) -> Chained<'a> {
2439 self.inner
2440 }
2441 pub fn buf(&self) -> &Vec<u8> {
2442 self.inner.buf()
2443 }
2444 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2445 self.inner.buf_mut()
2446 }
2447 fn get_index(&self, seq: u32) -> Option<u32> {
2448 let min = self.inner.first_seq;
2449 let max = min.wrapping_add(self.inner.lookups.len() as u32);
2450 return if min <= max {
2451 (min..max).contains(&seq).then(|| seq - min)
2452 } else if min <= seq {
2453 Some(seq - min)
2454 } else if seq < max {
2455 Some(u32::MAX - min + seq)
2456 } else {
2457 None
2458 };
2459 }
2460}
2461impl crate::traits::NetlinkChained for ChainedFinal<'_> {
2462 fn protonum(&self) -> u16 {
2463 PROTONUM
2464 }
2465 fn payload(&self) -> &[u8] {
2466 self.buf()
2467 }
2468 fn chain_len(&self) -> usize {
2469 self.inner.lookups.len()
2470 }
2471 fn get_index(&self, seq: u32) -> Option<usize> {
2472 self.get_index(seq).map(|n| n as usize)
2473 }
2474 fn name(&self, index: usize) -> &'static str {
2475 self.inner.lookups[index].0
2476 }
2477 fn lookup(&self, index: usize) -> LookupFn {
2478 self.inner.lookups[index].1
2479 }
2480}
2481impl Chained<'static> {
2482 pub fn new(first_seq: u32) -> Self {
2483 Self::new_from_buf(Vec::new(), first_seq)
2484 }
2485 pub fn new_from_buf(buf: Vec<u8>, first_seq: u32) -> Self {
2486 Self {
2487 buf: RequestBuf::Own(buf),
2488 first_seq,
2489 lookups: Vec::new(),
2490 last_header_offset: 0,
2491 last_kind: None,
2492 }
2493 }
2494 pub fn into_buf(self) -> Vec<u8> {
2495 match self.buf {
2496 RequestBuf::Own(buf) => buf,
2497 _ => unreachable!(),
2498 }
2499 }
2500}
2501impl<'a> Chained<'a> {
2502 pub fn new_with_buf(buf: &'a mut Vec<u8>, first_seq: u32) -> Self {
2503 Self {
2504 buf: RequestBuf::Ref(buf),
2505 first_seq,
2506 lookups: Vec::new(),
2507 last_header_offset: 0,
2508 last_kind: None,
2509 }
2510 }
2511 pub fn finalize(mut self) -> ChainedFinal<'a> {
2512 self.update_header();
2513 ChainedFinal { inner: self }
2514 }
2515 pub fn request(&mut self) -> Request<'_> {
2516 self.update_header();
2517 self.last_header_offset = self.buf().len();
2518 self.buf_mut().extend_from_slice(Nlmsghdr::new().as_slice());
2519 let mut request = Request::new_extend(self.buf.buf_mut());
2520 self.last_kind = None;
2521 request.writeback = Some(&mut self.last_kind);
2522 request
2523 }
2524 pub fn buf(&self) -> &Vec<u8> {
2525 self.buf.buf()
2526 }
2527 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2528 self.buf.buf_mut()
2529 }
2530 fn update_header(&mut self) {
2531 let Some(RequestInfo {
2532 protocol,
2533 flags,
2534 name,
2535 lookup,
2536 }) = self.last_kind
2537 else {
2538 if !self.buf().is_empty() {
2539 assert_eq!(self.last_header_offset + Nlmsghdr::len(), self.buf().len());
2540 self.buf.buf_mut().truncate(self.last_header_offset);
2541 }
2542 return;
2543 };
2544 let header_offset = self.last_header_offset;
2545 let request_type = match protocol {
2546 Protocol::Raw { request_type, .. } => request_type,
2547 Protocol::Generic(_) => unreachable!(),
2548 };
2549 let index = self.lookups.len();
2550 let seq = self.first_seq.wrapping_add(index as u32);
2551 self.lookups.push((name, lookup));
2552 let buf = self.buf_mut();
2553 align(buf);
2554 let header = Nlmsghdr {
2555 len: (buf.len() - header_offset) as u32,
2556 r#type: request_type,
2557 flags: flags | consts::NLM_F_REQUEST as u16 | consts::NLM_F_ACK as u16,
2558 seq,
2559 pid: 0,
2560 };
2561 buf[header_offset..(header_offset + 16)].clone_from_slice(header.as_slice());
2562 }
2563}
2564use crate::traits::LookupFn;
2565use crate::utils::RequestBuf;
2566#[derive(Debug)]
2567pub struct Request<'buf> {
2568 buf: RequestBuf<'buf>,
2569 flags: u16,
2570 writeback: Option<&'buf mut Option<RequestInfo>>,
2571}
2572#[allow(unused)]
2573#[derive(Debug, Clone)]
2574pub struct RequestInfo {
2575 protocol: Protocol,
2576 flags: u16,
2577 name: &'static str,
2578 lookup: LookupFn,
2579}
2580impl Request<'static> {
2581 pub fn new() -> Self {
2582 Self::new_from_buf(Vec::new())
2583 }
2584 pub fn new_from_buf(buf: Vec<u8>) -> Self {
2585 Self {
2586 flags: 0,
2587 buf: RequestBuf::Own(buf),
2588 writeback: None,
2589 }
2590 }
2591 pub fn into_buf(self) -> Vec<u8> {
2592 match self.buf {
2593 RequestBuf::Own(buf) => buf,
2594 _ => unreachable!(),
2595 }
2596 }
2597}
2598impl<'buf> Request<'buf> {
2599 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
2600 buf.clear();
2601 Self::new_extend(buf)
2602 }
2603 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
2604 Self {
2605 flags: 0,
2606 buf: RequestBuf::Ref(buf),
2607 writeback: None,
2608 }
2609 }
2610 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
2611 let Some(writeback) = &mut self.writeback else {
2612 return;
2613 };
2614 **writeback = Some(RequestInfo {
2615 protocol,
2616 flags: self.flags,
2617 name,
2618 lookup,
2619 })
2620 }
2621 pub fn buf(&self) -> &Vec<u8> {
2622 self.buf.buf()
2623 }
2624 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
2625 self.buf.buf_mut()
2626 }
2627 #[doc = "Set `NLM_F_CREATE` flag"]
2628 pub fn set_create(mut self) -> Self {
2629 self.flags |= consts::NLM_F_CREATE as u16;
2630 self
2631 }
2632 #[doc = "Set `NLM_F_EXCL` flag"]
2633 pub fn set_excl(mut self) -> Self {
2634 self.flags |= consts::NLM_F_EXCL as u16;
2635 self
2636 }
2637 #[doc = "Set `NLM_F_REPLACE` flag"]
2638 pub fn set_replace(mut self) -> Self {
2639 self.flags |= consts::NLM_F_REPLACE as u16;
2640 self
2641 }
2642 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
2643 pub fn set_change(self) -> Self {
2644 self.set_create().set_replace()
2645 }
2646 #[doc = "Set `NLM_F_APPEND` flag"]
2647 pub fn set_append(mut self) -> Self {
2648 self.flags |= consts::NLM_F_APPEND as u16;
2649 self
2650 }
2651 #[doc = "Set `self.flags |= flags`"]
2652 pub fn set_flags(mut self, flags: u16) -> Self {
2653 self.flags |= flags;
2654 self
2655 }
2656 #[doc = "Set `self.flags ^= self.flags & flags`"]
2657 pub fn unset_flags(mut self, flags: u16) -> Self {
2658 self.flags ^= self.flags & flags;
2659 self
2660 }
2661 #[doc = "Set `NLM_F_DUMP` flag"]
2662 fn set_dump(mut self) -> Self {
2663 self.flags |= consts::NLM_F_DUMP as u16;
2664 self
2665 }
2666 #[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"]
2667 pub fn op_getroute_dump(self, header: &Rtmsg) -> OpGetrouteDump<'buf> {
2668 let mut res = OpGetrouteDump::new(self, header);
2669 res.request
2670 .do_writeback(res.protocol(), "op-getroute-dump", OpGetrouteDump::lookup);
2671 res
2672 }
2673 #[doc = "Dump route information\\.\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"]
2674 pub fn op_getroute_do(self, header: &Rtmsg) -> OpGetrouteDo<'buf> {
2675 let mut res = OpGetrouteDo::new(self, header);
2676 res.request
2677 .do_writeback(res.protocol(), "op-getroute-do", OpGetrouteDo::lookup);
2678 res
2679 }
2680 #[doc = "Create a new route\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"]
2681 pub fn op_newroute_do(self, header: &Rtmsg) -> OpNewrouteDo<'buf> {
2682 let mut res = OpNewrouteDo::new(self, header);
2683 res.request
2684 .do_writeback(res.protocol(), "op-newroute-do", OpNewrouteDo::lookup);
2685 res
2686 }
2687 #[doc = "Delete an existing route\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"]
2688 pub fn op_delroute_do(self, header: &Rtmsg) -> OpDelrouteDo<'buf> {
2689 let mut res = OpDelrouteDo::new(self, header);
2690 res.request
2691 .do_writeback(res.protocol(), "op-delroute-do", OpDelrouteDo::lookup);
2692 res
2693 }
2694}
2695#[cfg(test)]
2696mod generated_tests {
2697 use super::*;
2698 #[test]
2699 fn tests() {
2700 let _ = IterableRouteAttrs::get_cacheinfo;
2701 let _ = IterableRouteAttrs::get_dport;
2702 let _ = IterableRouteAttrs::get_dst;
2703 let _ = IterableRouteAttrs::get_encap;
2704 let _ = IterableRouteAttrs::get_encap_type;
2705 let _ = IterableRouteAttrs::get_expires;
2706 let _ = IterableRouteAttrs::get_flow;
2707 let _ = IterableRouteAttrs::get_flowlabel;
2708 let _ = IterableRouteAttrs::get_gateway;
2709 let _ = IterableRouteAttrs::get_iif;
2710 let _ = IterableRouteAttrs::get_ip_proto;
2711 let _ = IterableRouteAttrs::get_mark;
2712 let _ = IterableRouteAttrs::get_metrics;
2713 let _ = IterableRouteAttrs::get_mfc_stats;
2714 let _ = IterableRouteAttrs::get_multipath;
2715 let _ = IterableRouteAttrs::get_newdst;
2716 let _ = IterableRouteAttrs::get_nh_id;
2717 let _ = IterableRouteAttrs::get_oif;
2718 let _ = IterableRouteAttrs::get_pad;
2719 let _ = IterableRouteAttrs::get_pref;
2720 let _ = IterableRouteAttrs::get_prefsrc;
2721 let _ = IterableRouteAttrs::get_priority;
2722 let _ = IterableRouteAttrs::get_sport;
2723 let _ = IterableRouteAttrs::get_src;
2724 let _ = IterableRouteAttrs::get_table;
2725 let _ = IterableRouteAttrs::get_ttl_propagate;
2726 let _ = IterableRouteAttrs::get_uid;
2727 let _ = IterableRouteAttrs::get_via;
2728 let _ = PushRouteAttrs::<&mut Vec<u8>>::nested_metrics;
2729 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_cacheinfo;
2730 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dport;
2731 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_dst;
2732 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap;
2733 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_encap_type;
2734 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_expires;
2735 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flow;
2736 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_flowlabel;
2737 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_gateway;
2738 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_iif;
2739 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ip_proto;
2740 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mark;
2741 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_mfc_stats;
2742 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_multipath;
2743 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_newdst;
2744 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_nh_id;
2745 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_oif;
2746 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pad;
2747 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_pref;
2748 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_prefsrc;
2749 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_priority;
2750 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_sport;
2751 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_src;
2752 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_table;
2753 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_ttl_propagate;
2754 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_uid;
2755 let _ = PushRouteAttrs::<&mut Vec<u8>>::push_via;
2756 }
2757}