1#![doc = "Netlink protocol to control WireGuard network devices.\n\nThe below enums and macros are for interfacing with WireGuard, using generic\nnetlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two\ncommands: get and set. Note that while they share many common attributes,\nthese two commands actually accept a slightly different set of inputs and\noutputs. These differences are noted under the individual attributes.\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)]
10#[cfg(test)]
11mod tests;
12use crate::builtin::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
13use crate::{
14 consts,
15 traits::{NetlinkRequest, Protocol},
16 utils::*,
17};
18pub const PROTONAME: &CStr = c"wireguard";
19pub const KEY_LEN: u64 = 32u64;
20#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
21#[derive(Debug, Clone, Copy)]
22pub enum WgdeviceFlags {
23 ReplacePeers = 1 << 0,
24}
25impl WgdeviceFlags {
26 pub fn from_value(value: u64) -> Option<Self> {
27 Some(match value {
28 n if n == 1 << 0 => Self::ReplacePeers,
29 _ => return None,
30 })
31 }
32}
33#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
34#[derive(Debug, Clone, Copy)]
35pub enum WgpeerFlags {
36 RemoveMe = 1 << 0,
37 ReplaceAllowedips = 1 << 1,
38 UpdateOnly = 1 << 2,
39}
40impl WgpeerFlags {
41 pub fn from_value(value: u64) -> Option<Self> {
42 Some(match value {
43 n if n == 1 << 0 => Self::RemoveMe,
44 n if n == 1 << 1 => Self::ReplaceAllowedips,
45 n if n == 1 << 2 => Self::UpdateOnly,
46 _ => return None,
47 })
48 }
49}
50#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
51#[derive(Debug, Clone, Copy)]
52pub enum WgallowedipFlags {
53 RemoveMe = 1 << 0,
54}
55impl WgallowedipFlags {
56 pub fn from_value(value: u64) -> Option<Self> {
57 Some(match value {
58 n if n == 1 << 0 => Self::RemoveMe,
59 _ => return None,
60 })
61 }
62}
63#[derive(Clone)]
64pub enum Wgdevice<'a> {
65 Ifindex(u32),
66 Ifname(&'a CStr),
67 #[doc = "Set to all zeros to remove."]
68 PrivateKey(&'a [u8]),
69 PublicKey(&'a [u8]),
70 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
71 Flags(u32),
72 #[doc = "Set as 0 to choose randomly."]
73 ListenPort(u16),
74 #[doc = "Set as 0 to disable."]
75 Fwmark(u32),
76 Peers(IterableArrayWgpeer<'a>),
77}
78impl<'a> IterableWgdevice<'a> {
79 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
80 let mut iter = self.clone();
81 iter.pos = 0;
82 for attr in iter {
83 if let Wgdevice::Ifindex(val) = attr? {
84 return Ok(val);
85 }
86 }
87 Err(ErrorContext::new_missing(
88 "Wgdevice",
89 "Ifindex",
90 self.orig_loc,
91 self.buf.as_ptr() as usize,
92 ))
93 }
94 pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
95 let mut iter = self.clone();
96 iter.pos = 0;
97 for attr in iter {
98 if let Wgdevice::Ifname(val) = attr? {
99 return Ok(val);
100 }
101 }
102 Err(ErrorContext::new_missing(
103 "Wgdevice",
104 "Ifname",
105 self.orig_loc,
106 self.buf.as_ptr() as usize,
107 ))
108 }
109 #[doc = "Set to all zeros to remove."]
110 pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
111 let mut iter = self.clone();
112 iter.pos = 0;
113 for attr in iter {
114 if let Wgdevice::PrivateKey(val) = attr? {
115 return Ok(val);
116 }
117 }
118 Err(ErrorContext::new_missing(
119 "Wgdevice",
120 "PrivateKey",
121 self.orig_loc,
122 self.buf.as_ptr() as usize,
123 ))
124 }
125 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
126 let mut iter = self.clone();
127 iter.pos = 0;
128 for attr in iter {
129 if let Wgdevice::PublicKey(val) = attr? {
130 return Ok(val);
131 }
132 }
133 Err(ErrorContext::new_missing(
134 "Wgdevice",
135 "PublicKey",
136 self.orig_loc,
137 self.buf.as_ptr() as usize,
138 ))
139 }
140 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
141 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
142 let mut iter = self.clone();
143 iter.pos = 0;
144 for attr in iter {
145 if let Wgdevice::Flags(val) = attr? {
146 return Ok(val);
147 }
148 }
149 Err(ErrorContext::new_missing(
150 "Wgdevice",
151 "Flags",
152 self.orig_loc,
153 self.buf.as_ptr() as usize,
154 ))
155 }
156 #[doc = "Set as 0 to choose randomly."]
157 pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
158 let mut iter = self.clone();
159 iter.pos = 0;
160 for attr in iter {
161 if let Wgdevice::ListenPort(val) = attr? {
162 return Ok(val);
163 }
164 }
165 Err(ErrorContext::new_missing(
166 "Wgdevice",
167 "ListenPort",
168 self.orig_loc,
169 self.buf.as_ptr() as usize,
170 ))
171 }
172 #[doc = "Set as 0 to disable."]
173 pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
174 let mut iter = self.clone();
175 iter.pos = 0;
176 for attr in iter {
177 if let Wgdevice::Fwmark(val) = attr? {
178 return Ok(val);
179 }
180 }
181 Err(ErrorContext::new_missing(
182 "Wgdevice",
183 "Fwmark",
184 self.orig_loc,
185 self.buf.as_ptr() as usize,
186 ))
187 }
188 pub fn get_peers(
189 &self,
190 ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
191 for attr in self.clone() {
192 if let Wgdevice::Peers(val) = attr? {
193 return Ok(ArrayIterable::new(val));
194 }
195 }
196 Err(ErrorContext::new_missing(
197 "Wgdevice",
198 "Peers",
199 self.orig_loc,
200 self.buf.as_ptr() as usize,
201 ))
202 }
203}
204impl<'a> Wgpeer<'a> {
205 pub fn new_array(buf: &[u8]) -> IterableArrayWgpeer<'_> {
206 IterableArrayWgpeer::with_loc(buf, buf.as_ptr() as usize)
207 }
208}
209#[derive(Clone, Copy, Default)]
210pub struct IterableArrayWgpeer<'a> {
211 buf: &'a [u8],
212 pos: usize,
213 orig_loc: usize,
214}
215impl<'a> IterableArrayWgpeer<'a> {
216 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
217 Self {
218 buf,
219 pos: 0,
220 orig_loc,
221 }
222 }
223 pub fn get_buf(&self) -> &'a [u8] {
224 self.buf
225 }
226}
227impl<'a> Iterator for IterableArrayWgpeer<'a> {
228 type Item = Result<IterableWgpeer<'a>, ErrorContext>;
229 fn next(&mut self) -> Option<Self::Item> {
230 if self.buf.len() == self.pos {
231 return None;
232 }
233 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
234 {
235 return Some(Ok(IterableWgpeer::with_loc(next, self.orig_loc)));
236 }
237 }
238 Some(Err(ErrorContext::new(
239 "Wgpeer",
240 None,
241 self.orig_loc,
242 self.buf.as_ptr().wrapping_add(self.pos) as usize,
243 )))
244 }
245}
246impl<'a> Wgdevice<'a> {
247 pub fn new(buf: &'a [u8]) -> IterableWgdevice<'a> {
248 IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
249 }
250 fn attr_from_type(r#type: u16) -> Option<&'static str> {
251 let res = match r#type {
252 0u16 => "Unspec",
253 1u16 => "Ifindex",
254 2u16 => "Ifname",
255 3u16 => "PrivateKey",
256 4u16 => "PublicKey",
257 5u16 => "Flags",
258 6u16 => "ListenPort",
259 7u16 => "Fwmark",
260 8u16 => "Peers",
261 _ => return None,
262 };
263 Some(res)
264 }
265}
266#[derive(Clone, Copy, Default)]
267pub struct IterableWgdevice<'a> {
268 buf: &'a [u8],
269 pos: usize,
270 orig_loc: usize,
271}
272impl<'a> IterableWgdevice<'a> {
273 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
274 Self {
275 buf,
276 pos: 0,
277 orig_loc,
278 }
279 }
280 pub fn get_buf(&self) -> &'a [u8] {
281 self.buf
282 }
283}
284impl<'a> Iterator for IterableWgdevice<'a> {
285 type Item = Result<Wgdevice<'a>, ErrorContext>;
286 fn next(&mut self) -> Option<Self::Item> {
287 if self.buf.len() == self.pos {
288 return None;
289 }
290 let pos = self.pos;
291 let mut r#type = None;
292 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
293 r#type = Some(header.r#type);
294 let res = match header.r#type {
295 1u16 => Wgdevice::Ifindex({
296 let res = parse_u32(next);
297 let Some(val) = res else { break };
298 val
299 }),
300 2u16 => Wgdevice::Ifname({
301 let res = CStr::from_bytes_with_nul(next).ok();
302 let Some(val) = res else { break };
303 val
304 }),
305 3u16 => Wgdevice::PrivateKey({
306 let res = Some(next);
307 let Some(val) = res else { break };
308 val
309 }),
310 4u16 => Wgdevice::PublicKey({
311 let res = Some(next);
312 let Some(val) = res else { break };
313 val
314 }),
315 5u16 => Wgdevice::Flags({
316 let res = parse_u32(next);
317 let Some(val) = res else { break };
318 val
319 }),
320 6u16 => Wgdevice::ListenPort({
321 let res = parse_u16(next);
322 let Some(val) = res else { break };
323 val
324 }),
325 7u16 => Wgdevice::Fwmark({
326 let res = parse_u32(next);
327 let Some(val) = res else { break };
328 val
329 }),
330 8u16 => Wgdevice::Peers({
331 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
332 let Some(val) = res else { break };
333 val
334 }),
335 n => {
336 if cfg!(any(test, feature = "deny-unknown-attrs")) {
337 break;
338 } else {
339 continue;
340 }
341 }
342 };
343 return Some(Ok(res));
344 }
345 Some(Err(ErrorContext::new(
346 "Wgdevice",
347 r#type.and_then(|t| Wgdevice::attr_from_type(t)),
348 self.orig_loc,
349 self.buf.as_ptr().wrapping_add(pos) as usize,
350 )))
351 }
352}
353impl std::fmt::Debug for IterableArrayWgpeer<'_> {
354 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355 fmt.debug_list()
356 .entries(self.clone().map(FlattenErrorContext))
357 .finish()
358 }
359}
360impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362 let mut fmt = f.debug_struct("Wgdevice");
363 for attr in self.clone() {
364 let attr = match attr {
365 Ok(a) => a,
366 Err(err) => {
367 fmt.finish()?;
368 f.write_str("Err(")?;
369 err.fmt(f)?;
370 return f.write_str(")");
371 }
372 };
373 match attr {
374 Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
375 Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
376 Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
377 Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
378 Wgdevice::Flags(val) => {
379 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
380 }
381 Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
382 Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
383 Wgdevice::Peers(val) => fmt.field("Peers", &val),
384 };
385 }
386 fmt.finish()
387 }
388}
389impl IterableWgdevice<'_> {
390 pub fn lookup_attr(
391 &self,
392 offset: usize,
393 missing_type: Option<u16>,
394 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
395 let mut stack = Vec::new();
396 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
397 if cur == offset {
398 stack.push(("Wgdevice", offset));
399 return (
400 stack,
401 missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
402 );
403 }
404 if cur > offset || cur + self.buf.len() < offset {
405 return (stack, None);
406 }
407 let mut attrs = self.clone();
408 let mut last_off = cur + attrs.pos;
409 let mut missing = None;
410 while let Some(attr) = attrs.next() {
411 let Ok(attr) = attr else { break };
412 match attr {
413 Wgdevice::Ifindex(val) => {
414 if last_off == offset {
415 stack.push(("Ifindex", last_off));
416 break;
417 }
418 }
419 Wgdevice::Ifname(val) => {
420 if last_off == offset {
421 stack.push(("Ifname", last_off));
422 break;
423 }
424 }
425 Wgdevice::PrivateKey(val) => {
426 if last_off == offset {
427 stack.push(("PrivateKey", last_off));
428 break;
429 }
430 }
431 Wgdevice::PublicKey(val) => {
432 if last_off == offset {
433 stack.push(("PublicKey", last_off));
434 break;
435 }
436 }
437 Wgdevice::Flags(val) => {
438 if last_off == offset {
439 stack.push(("Flags", last_off));
440 break;
441 }
442 }
443 Wgdevice::ListenPort(val) => {
444 if last_off == offset {
445 stack.push(("ListenPort", last_off));
446 break;
447 }
448 }
449 Wgdevice::Fwmark(val) => {
450 if last_off == offset {
451 stack.push(("Fwmark", last_off));
452 break;
453 }
454 }
455 Wgdevice::Peers(val) => {
456 for entry in val {
457 let Ok(attr) = entry else { break };
458 (stack, missing) = attr.lookup_attr(offset, missing_type);
459 if !stack.is_empty() {
460 break;
461 }
462 }
463 if !stack.is_empty() {
464 stack.push(("Peers", last_off));
465 break;
466 }
467 }
468 _ => {}
469 };
470 last_off = cur + attrs.pos;
471 }
472 if !stack.is_empty() {
473 stack.push(("Wgdevice", cur));
474 }
475 (stack, missing)
476 }
477}
478#[derive(Clone)]
479pub enum Wgpeer<'a> {
480 PublicKey(&'a [u8]),
481 #[doc = "Set as all zeros to remove."]
482 PresharedKey(&'a [u8]),
483 #[doc = "0 and/or WGPEER_F_REMOVE_ME if the specified peer should not\nexist at the end of the operation, rather than added/updated\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
484 Flags(u32),
485 #[doc = "struct sockaddr_in or struct sockaddr_in6"]
486 Endpoint(std::net::SocketAddr),
487 #[doc = "Set as 0 to disable."]
488 PersistentKeepaliveInterval(u16),
489 LastHandshakeTime(PushKernelTimespec),
490 RxBytes(u64),
491 TxBytes(u64),
492 Allowedips(IterableArrayWgallowedip<'a>),
493 #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
494 ProtocolVersion(u32),
495}
496impl<'a> IterableWgpeer<'a> {
497 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
498 let mut iter = self.clone();
499 iter.pos = 0;
500 for attr in iter {
501 if let Wgpeer::PublicKey(val) = attr? {
502 return Ok(val);
503 }
504 }
505 Err(ErrorContext::new_missing(
506 "Wgpeer",
507 "PublicKey",
508 self.orig_loc,
509 self.buf.as_ptr() as usize,
510 ))
511 }
512 #[doc = "Set as all zeros to remove."]
513 pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
514 let mut iter = self.clone();
515 iter.pos = 0;
516 for attr in iter {
517 if let Wgpeer::PresharedKey(val) = attr? {
518 return Ok(val);
519 }
520 }
521 Err(ErrorContext::new_missing(
522 "Wgpeer",
523 "PresharedKey",
524 self.orig_loc,
525 self.buf.as_ptr() as usize,
526 ))
527 }
528 #[doc = "0 and/or WGPEER_F_REMOVE_ME if the specified peer should not\nexist at the end of the operation, rather than added/updated\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
529 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
530 let mut iter = self.clone();
531 iter.pos = 0;
532 for attr in iter {
533 if let Wgpeer::Flags(val) = attr? {
534 return Ok(val);
535 }
536 }
537 Err(ErrorContext::new_missing(
538 "Wgpeer",
539 "Flags",
540 self.orig_loc,
541 self.buf.as_ptr() as usize,
542 ))
543 }
544 #[doc = "struct sockaddr_in or struct sockaddr_in6"]
545 pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
546 let mut iter = self.clone();
547 iter.pos = 0;
548 for attr in iter {
549 if let Wgpeer::Endpoint(val) = attr? {
550 return Ok(val);
551 }
552 }
553 Err(ErrorContext::new_missing(
554 "Wgpeer",
555 "Endpoint",
556 self.orig_loc,
557 self.buf.as_ptr() as usize,
558 ))
559 }
560 #[doc = "Set as 0 to disable."]
561 pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
562 let mut iter = self.clone();
563 iter.pos = 0;
564 for attr in iter {
565 if let Wgpeer::PersistentKeepaliveInterval(val) = attr? {
566 return Ok(val);
567 }
568 }
569 Err(ErrorContext::new_missing(
570 "Wgpeer",
571 "PersistentKeepaliveInterval",
572 self.orig_loc,
573 self.buf.as_ptr() as usize,
574 ))
575 }
576 pub fn get_last_handshake_time(&self) -> Result<PushKernelTimespec, ErrorContext> {
577 let mut iter = self.clone();
578 iter.pos = 0;
579 for attr in iter {
580 if let Wgpeer::LastHandshakeTime(val) = attr? {
581 return Ok(val);
582 }
583 }
584 Err(ErrorContext::new_missing(
585 "Wgpeer",
586 "LastHandshakeTime",
587 self.orig_loc,
588 self.buf.as_ptr() as usize,
589 ))
590 }
591 pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
592 let mut iter = self.clone();
593 iter.pos = 0;
594 for attr in iter {
595 if let Wgpeer::RxBytes(val) = attr? {
596 return Ok(val);
597 }
598 }
599 Err(ErrorContext::new_missing(
600 "Wgpeer",
601 "RxBytes",
602 self.orig_loc,
603 self.buf.as_ptr() as usize,
604 ))
605 }
606 pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
607 let mut iter = self.clone();
608 iter.pos = 0;
609 for attr in iter {
610 if let Wgpeer::TxBytes(val) = attr? {
611 return Ok(val);
612 }
613 }
614 Err(ErrorContext::new_missing(
615 "Wgpeer",
616 "TxBytes",
617 self.orig_loc,
618 self.buf.as_ptr() as usize,
619 ))
620 }
621 pub fn get_allowedips(
622 &self,
623 ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
624 {
625 for attr in self.clone() {
626 if let Wgpeer::Allowedips(val) = attr? {
627 return Ok(ArrayIterable::new(val));
628 }
629 }
630 Err(ErrorContext::new_missing(
631 "Wgpeer",
632 "Allowedips",
633 self.orig_loc,
634 self.buf.as_ptr() as usize,
635 ))
636 }
637 #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
638 pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
639 let mut iter = self.clone();
640 iter.pos = 0;
641 for attr in iter {
642 if let Wgpeer::ProtocolVersion(val) = attr? {
643 return Ok(val);
644 }
645 }
646 Err(ErrorContext::new_missing(
647 "Wgpeer",
648 "ProtocolVersion",
649 self.orig_loc,
650 self.buf.as_ptr() as usize,
651 ))
652 }
653}
654impl Wgallowedip {
655 pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
656 IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
657 }
658}
659#[derive(Clone, Copy, Default)]
660pub struct IterableArrayWgallowedip<'a> {
661 buf: &'a [u8],
662 pos: usize,
663 orig_loc: usize,
664}
665impl<'a> IterableArrayWgallowedip<'a> {
666 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
667 Self {
668 buf,
669 pos: 0,
670 orig_loc,
671 }
672 }
673 pub fn get_buf(&self) -> &'a [u8] {
674 self.buf
675 }
676}
677impl<'a> Iterator for IterableArrayWgallowedip<'a> {
678 type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
679 fn next(&mut self) -> Option<Self::Item> {
680 if self.buf.len() == self.pos {
681 return None;
682 }
683 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
684 {
685 return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
686 }
687 }
688 Some(Err(ErrorContext::new(
689 "Wgallowedip",
690 None,
691 self.orig_loc,
692 self.buf.as_ptr().wrapping_add(self.pos) as usize,
693 )))
694 }
695}
696impl<'a> Wgpeer<'a> {
697 pub fn new(buf: &'a [u8]) -> IterableWgpeer<'a> {
698 IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
699 }
700 fn attr_from_type(r#type: u16) -> Option<&'static str> {
701 let res = match r#type {
702 0u16 => "Unspec",
703 1u16 => "PublicKey",
704 2u16 => "PresharedKey",
705 3u16 => "Flags",
706 4u16 => "Endpoint",
707 5u16 => "PersistentKeepaliveInterval",
708 6u16 => "LastHandshakeTime",
709 7u16 => "RxBytes",
710 8u16 => "TxBytes",
711 9u16 => "Allowedips",
712 10u16 => "ProtocolVersion",
713 _ => return None,
714 };
715 Some(res)
716 }
717}
718#[derive(Clone, Copy, Default)]
719pub struct IterableWgpeer<'a> {
720 buf: &'a [u8],
721 pos: usize,
722 orig_loc: usize,
723}
724impl<'a> IterableWgpeer<'a> {
725 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
726 Self {
727 buf,
728 pos: 0,
729 orig_loc,
730 }
731 }
732 pub fn get_buf(&self) -> &'a [u8] {
733 self.buf
734 }
735}
736impl<'a> Iterator for IterableWgpeer<'a> {
737 type Item = Result<Wgpeer<'a>, ErrorContext>;
738 fn next(&mut self) -> Option<Self::Item> {
739 if self.buf.len() == self.pos {
740 return None;
741 }
742 let pos = self.pos;
743 let mut r#type = None;
744 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
745 r#type = Some(header.r#type);
746 let res = match header.r#type {
747 1u16 => Wgpeer::PublicKey({
748 let res = Some(next);
749 let Some(val) = res else { break };
750 val
751 }),
752 2u16 => Wgpeer::PresharedKey({
753 let res = Some(next);
754 let Some(val) = res else { break };
755 val
756 }),
757 3u16 => Wgpeer::Flags({
758 let res = parse_u32(next);
759 let Some(val) = res else { break };
760 val
761 }),
762 4u16 => Wgpeer::Endpoint({
763 let res = parse_sockaddr(next);
764 let Some(val) = res else { break };
765 val
766 }),
767 5u16 => Wgpeer::PersistentKeepaliveInterval({
768 let res = parse_u16(next);
769 let Some(val) = res else { break };
770 val
771 }),
772 6u16 => Wgpeer::LastHandshakeTime({
773 let res = PushKernelTimespec::new_from_slice(next);
774 let Some(val) = res else { break };
775 val
776 }),
777 7u16 => Wgpeer::RxBytes({
778 let res = parse_u64(next);
779 let Some(val) = res else { break };
780 val
781 }),
782 8u16 => Wgpeer::TxBytes({
783 let res = parse_u64(next);
784 let Some(val) = res else { break };
785 val
786 }),
787 9u16 => Wgpeer::Allowedips({
788 let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
789 let Some(val) = res else { break };
790 val
791 }),
792 10u16 => Wgpeer::ProtocolVersion({
793 let res = parse_u32(next);
794 let Some(val) = res else { break };
795 val
796 }),
797 n => {
798 if cfg!(any(test, feature = "deny-unknown-attrs")) {
799 break;
800 } else {
801 continue;
802 }
803 }
804 };
805 return Some(Ok(res));
806 }
807 Some(Err(ErrorContext::new(
808 "Wgpeer",
809 r#type.and_then(|t| Wgpeer::attr_from_type(t)),
810 self.orig_loc,
811 self.buf.as_ptr().wrapping_add(pos) as usize,
812 )))
813 }
814}
815impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
816 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
817 fmt.debug_list()
818 .entries(self.clone().map(FlattenErrorContext))
819 .finish()
820 }
821}
822impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
823 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
824 let mut fmt = f.debug_struct("Wgpeer");
825 for attr in self.clone() {
826 let attr = match attr {
827 Ok(a) => a,
828 Err(err) => {
829 fmt.finish()?;
830 f.write_str("Err(")?;
831 err.fmt(f)?;
832 return f.write_str(")");
833 }
834 };
835 match attr {
836 Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
837 Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
838 Wgpeer::Flags(val) => {
839 fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
840 }
841 Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
842 Wgpeer::PersistentKeepaliveInterval(val) => {
843 fmt.field("PersistentKeepaliveInterval", &val)
844 }
845 Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
846 Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
847 Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
848 Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
849 Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
850 };
851 }
852 fmt.finish()
853 }
854}
855impl IterableWgpeer<'_> {
856 pub fn lookup_attr(
857 &self,
858 offset: usize,
859 missing_type: Option<u16>,
860 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
861 let mut stack = Vec::new();
862 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
863 if cur == offset {
864 stack.push(("Wgpeer", offset));
865 return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
866 }
867 if cur > offset || cur + self.buf.len() < offset {
868 return (stack, None);
869 }
870 let mut attrs = self.clone();
871 let mut last_off = cur + attrs.pos;
872 let mut missing = None;
873 while let Some(attr) = attrs.next() {
874 let Ok(attr) = attr else { break };
875 match attr {
876 Wgpeer::PublicKey(val) => {
877 if last_off == offset {
878 stack.push(("PublicKey", last_off));
879 break;
880 }
881 }
882 Wgpeer::PresharedKey(val) => {
883 if last_off == offset {
884 stack.push(("PresharedKey", last_off));
885 break;
886 }
887 }
888 Wgpeer::Flags(val) => {
889 if last_off == offset {
890 stack.push(("Flags", last_off));
891 break;
892 }
893 }
894 Wgpeer::Endpoint(val) => {
895 if last_off == offset {
896 stack.push(("Endpoint", last_off));
897 break;
898 }
899 }
900 Wgpeer::PersistentKeepaliveInterval(val) => {
901 if last_off == offset {
902 stack.push(("PersistentKeepaliveInterval", last_off));
903 break;
904 }
905 }
906 Wgpeer::LastHandshakeTime(val) => {
907 if last_off == offset {
908 stack.push(("LastHandshakeTime", last_off));
909 break;
910 }
911 }
912 Wgpeer::RxBytes(val) => {
913 if last_off == offset {
914 stack.push(("RxBytes", last_off));
915 break;
916 }
917 }
918 Wgpeer::TxBytes(val) => {
919 if last_off == offset {
920 stack.push(("TxBytes", last_off));
921 break;
922 }
923 }
924 Wgpeer::Allowedips(val) => {
925 for entry in val {
926 let Ok(attr) = entry else { break };
927 (stack, missing) = attr.lookup_attr(offset, missing_type);
928 if !stack.is_empty() {
929 break;
930 }
931 }
932 if !stack.is_empty() {
933 stack.push(("Allowedips", last_off));
934 break;
935 }
936 }
937 Wgpeer::ProtocolVersion(val) => {
938 if last_off == offset {
939 stack.push(("ProtocolVersion", last_off));
940 break;
941 }
942 }
943 _ => {}
944 };
945 last_off = cur + attrs.pos;
946 }
947 if !stack.is_empty() {
948 stack.push(("Wgpeer", cur));
949 }
950 (stack, missing)
951 }
952}
953#[derive(Clone)]
954pub enum Wgallowedip {
955 Family(u16),
956 #[doc = "struct in_addr or struct in6_add"]
957 Ipaddr(std::net::IpAddr),
958 CidrMask(u8),
959 #[doc = "WGALLOWEDIP_F_REMOVE_ME if the specified IP should be removed;\notherwise, this IP will be added if it is not already present.\n\nAssociated type: \"WgallowedipFlags\" (enum)"]
960 Flags(u32),
961}
962impl<'a> IterableWgallowedip<'a> {
963 pub fn get_family(&self) -> Result<u16, ErrorContext> {
964 let mut iter = self.clone();
965 iter.pos = 0;
966 for attr in iter {
967 if let Wgallowedip::Family(val) = attr? {
968 return Ok(val);
969 }
970 }
971 Err(ErrorContext::new_missing(
972 "Wgallowedip",
973 "Family",
974 self.orig_loc,
975 self.buf.as_ptr() as usize,
976 ))
977 }
978 #[doc = "struct in_addr or struct in6_add"]
979 pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
980 let mut iter = self.clone();
981 iter.pos = 0;
982 for attr in iter {
983 if let Wgallowedip::Ipaddr(val) = attr? {
984 return Ok(val);
985 }
986 }
987 Err(ErrorContext::new_missing(
988 "Wgallowedip",
989 "Ipaddr",
990 self.orig_loc,
991 self.buf.as_ptr() as usize,
992 ))
993 }
994 pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
995 let mut iter = self.clone();
996 iter.pos = 0;
997 for attr in iter {
998 if let Wgallowedip::CidrMask(val) = attr? {
999 return Ok(val);
1000 }
1001 }
1002 Err(ErrorContext::new_missing(
1003 "Wgallowedip",
1004 "CidrMask",
1005 self.orig_loc,
1006 self.buf.as_ptr() as usize,
1007 ))
1008 }
1009 #[doc = "WGALLOWEDIP_F_REMOVE_ME if the specified IP should be removed;\notherwise, this IP will be added if it is not already present.\n\nAssociated type: \"WgallowedipFlags\" (enum)"]
1010 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1011 let mut iter = self.clone();
1012 iter.pos = 0;
1013 for attr in iter {
1014 if let Wgallowedip::Flags(val) = attr? {
1015 return Ok(val);
1016 }
1017 }
1018 Err(ErrorContext::new_missing(
1019 "Wgallowedip",
1020 "Flags",
1021 self.orig_loc,
1022 self.buf.as_ptr() as usize,
1023 ))
1024 }
1025}
1026impl Wgallowedip {
1027 pub fn new(buf: &'_ [u8]) -> IterableWgallowedip<'_> {
1028 IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1029 }
1030 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1031 let res = match r#type {
1032 0u16 => "Unspec",
1033 1u16 => "Family",
1034 2u16 => "Ipaddr",
1035 3u16 => "CidrMask",
1036 4u16 => "Flags",
1037 _ => return None,
1038 };
1039 Some(res)
1040 }
1041}
1042#[derive(Clone, Copy, Default)]
1043pub struct IterableWgallowedip<'a> {
1044 buf: &'a [u8],
1045 pos: usize,
1046 orig_loc: usize,
1047}
1048impl<'a> IterableWgallowedip<'a> {
1049 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1050 Self {
1051 buf,
1052 pos: 0,
1053 orig_loc,
1054 }
1055 }
1056 pub fn get_buf(&self) -> &'a [u8] {
1057 self.buf
1058 }
1059}
1060impl<'a> Iterator for IterableWgallowedip<'a> {
1061 type Item = Result<Wgallowedip, ErrorContext>;
1062 fn next(&mut self) -> Option<Self::Item> {
1063 if self.buf.len() == self.pos {
1064 return None;
1065 }
1066 let pos = self.pos;
1067 let mut r#type = None;
1068 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1069 r#type = Some(header.r#type);
1070 let res = match header.r#type {
1071 1u16 => Wgallowedip::Family({
1072 let res = parse_u16(next);
1073 let Some(val) = res else { break };
1074 val
1075 }),
1076 2u16 => Wgallowedip::Ipaddr({
1077 let res = parse_ip(next);
1078 let Some(val) = res else { break };
1079 val
1080 }),
1081 3u16 => Wgallowedip::CidrMask({
1082 let res = parse_u8(next);
1083 let Some(val) = res else { break };
1084 val
1085 }),
1086 4u16 => Wgallowedip::Flags({
1087 let res = parse_u32(next);
1088 let Some(val) = res else { break };
1089 val
1090 }),
1091 n => {
1092 if cfg!(any(test, feature = "deny-unknown-attrs")) {
1093 break;
1094 } else {
1095 continue;
1096 }
1097 }
1098 };
1099 return Some(Ok(res));
1100 }
1101 Some(Err(ErrorContext::new(
1102 "Wgallowedip",
1103 r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1104 self.orig_loc,
1105 self.buf.as_ptr().wrapping_add(pos) as usize,
1106 )))
1107 }
1108}
1109impl std::fmt::Debug for IterableWgallowedip<'_> {
1110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1111 let mut fmt = f.debug_struct("Wgallowedip");
1112 for attr in self.clone() {
1113 let attr = match attr {
1114 Ok(a) => a,
1115 Err(err) => {
1116 fmt.finish()?;
1117 f.write_str("Err(")?;
1118 err.fmt(f)?;
1119 return f.write_str(")");
1120 }
1121 };
1122 match attr {
1123 Wgallowedip::Family(val) => fmt.field("Family", &val),
1124 Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1125 Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1126 Wgallowedip::Flags(val) => fmt.field(
1127 "Flags",
1128 &FormatFlags(val.into(), WgallowedipFlags::from_value),
1129 ),
1130 };
1131 }
1132 fmt.finish()
1133 }
1134}
1135impl IterableWgallowedip<'_> {
1136 pub fn lookup_attr(
1137 &self,
1138 offset: usize,
1139 missing_type: Option<u16>,
1140 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1141 let mut stack = Vec::new();
1142 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1143 if cur == offset {
1144 stack.push(("Wgallowedip", offset));
1145 return (
1146 stack,
1147 missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1148 );
1149 }
1150 if cur > offset || cur + self.buf.len() < offset {
1151 return (stack, None);
1152 }
1153 let mut attrs = self.clone();
1154 let mut last_off = cur + attrs.pos;
1155 while let Some(attr) = attrs.next() {
1156 let Ok(attr) = attr else { break };
1157 match attr {
1158 Wgallowedip::Family(val) => {
1159 if last_off == offset {
1160 stack.push(("Family", last_off));
1161 break;
1162 }
1163 }
1164 Wgallowedip::Ipaddr(val) => {
1165 if last_off == offset {
1166 stack.push(("Ipaddr", last_off));
1167 break;
1168 }
1169 }
1170 Wgallowedip::CidrMask(val) => {
1171 if last_off == offset {
1172 stack.push(("CidrMask", last_off));
1173 break;
1174 }
1175 }
1176 Wgallowedip::Flags(val) => {
1177 if last_off == offset {
1178 stack.push(("Flags", last_off));
1179 break;
1180 }
1181 }
1182 _ => {}
1183 };
1184 last_off = cur + attrs.pos;
1185 }
1186 if !stack.is_empty() {
1187 stack.push(("Wgallowedip", cur));
1188 }
1189 (stack, None)
1190 }
1191}
1192pub struct PushWgdevice<Prev: Rec> {
1193 pub(crate) prev: Option<Prev>,
1194 pub(crate) header_offset: Option<usize>,
1195}
1196impl<Prev: Rec> Rec for PushWgdevice<Prev> {
1197 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1198 self.prev.as_mut().unwrap().as_rec_mut()
1199 }
1200}
1201pub struct PushArrayWgpeer<Prev: Rec> {
1202 pub(crate) prev: Option<Prev>,
1203 pub(crate) header_offset: Option<usize>,
1204 pub(crate) counter: u16,
1205}
1206impl<Prev: Rec> Rec for PushArrayWgpeer<Prev> {
1207 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1208 self.prev.as_mut().unwrap().as_rec_mut()
1209 }
1210}
1211impl<Prev: Rec> PushArrayWgpeer<Prev> {
1212 pub fn new(prev: Prev) -> Self {
1213 Self {
1214 prev: Some(prev),
1215 header_offset: None,
1216 counter: 0,
1217 }
1218 }
1219 pub fn end_array(mut self) -> Prev {
1220 let mut prev = self.prev.take().unwrap();
1221 if let Some(header_offset) = &self.header_offset {
1222 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1223 }
1224 prev
1225 }
1226 pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1227 let index = self.counter;
1228 self.counter += 1;
1229 let header_offset = push_nested_header(self.as_rec_mut(), index);
1230 PushWgpeer {
1231 prev: Some(self),
1232 header_offset: Some(header_offset),
1233 }
1234 }
1235}
1236impl<Prev: Rec> Drop for PushArrayWgpeer<Prev> {
1237 fn drop(&mut self) {
1238 if let Some(prev) = &mut self.prev {
1239 if let Some(header_offset) = &self.header_offset {
1240 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1241 }
1242 }
1243 }
1244}
1245impl<Prev: Rec> PushWgdevice<Prev> {
1246 pub fn new(prev: Prev) -> Self {
1247 Self {
1248 prev: Some(prev),
1249 header_offset: None,
1250 }
1251 }
1252 pub fn end_nested(mut self) -> Prev {
1253 let mut prev = self.prev.take().unwrap();
1254 if let Some(header_offset) = &self.header_offset {
1255 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1256 }
1257 prev
1258 }
1259 pub fn push_ifindex(mut self, value: u32) -> Self {
1260 push_header(self.as_rec_mut(), 1u16, 4 as u16);
1261 self.as_rec_mut().extend(value.to_ne_bytes());
1262 self
1263 }
1264 pub fn push_ifname(mut self, value: &CStr) -> Self {
1265 push_header(
1266 self.as_rec_mut(),
1267 2u16,
1268 value.to_bytes_with_nul().len() as u16,
1269 );
1270 self.as_rec_mut().extend(value.to_bytes_with_nul());
1271 self
1272 }
1273 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1274 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1275 self.as_rec_mut().extend(value);
1276 self.as_rec_mut().push(0);
1277 self
1278 }
1279 #[doc = "Set to all zeros to remove."]
1280 pub fn push_private_key(mut self, value: &[u8]) -> Self {
1281 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1282 self.as_rec_mut().extend(value);
1283 self
1284 }
1285 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1286 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1287 self.as_rec_mut().extend(value);
1288 self
1289 }
1290 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1291 pub fn push_flags(mut self, value: u32) -> Self {
1292 push_header(self.as_rec_mut(), 5u16, 4 as u16);
1293 self.as_rec_mut().extend(value.to_ne_bytes());
1294 self
1295 }
1296 #[doc = "Set as 0 to choose randomly."]
1297 pub fn push_listen_port(mut self, value: u16) -> Self {
1298 push_header(self.as_rec_mut(), 6u16, 2 as u16);
1299 self.as_rec_mut().extend(value.to_ne_bytes());
1300 self
1301 }
1302 #[doc = "Set as 0 to disable."]
1303 pub fn push_fwmark(mut self, value: u32) -> Self {
1304 push_header(self.as_rec_mut(), 7u16, 4 as u16);
1305 self.as_rec_mut().extend(value.to_ne_bytes());
1306 self
1307 }
1308 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1309 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1310 PushArrayWgpeer {
1311 prev: Some(self),
1312 header_offset: Some(header_offset),
1313 counter: 0,
1314 }
1315 }
1316}
1317impl<Prev: Rec> Drop for PushWgdevice<Prev> {
1318 fn drop(&mut self) {
1319 if let Some(prev) = &mut self.prev {
1320 if let Some(header_offset) = &self.header_offset {
1321 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1322 }
1323 }
1324 }
1325}
1326pub struct PushWgpeer<Prev: Rec> {
1327 pub(crate) prev: Option<Prev>,
1328 pub(crate) header_offset: Option<usize>,
1329}
1330impl<Prev: Rec> Rec for PushWgpeer<Prev> {
1331 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1332 self.prev.as_mut().unwrap().as_rec_mut()
1333 }
1334}
1335pub struct PushArrayWgallowedip<Prev: Rec> {
1336 pub(crate) prev: Option<Prev>,
1337 pub(crate) header_offset: Option<usize>,
1338 pub(crate) counter: u16,
1339}
1340impl<Prev: Rec> Rec for PushArrayWgallowedip<Prev> {
1341 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1342 self.prev.as_mut().unwrap().as_rec_mut()
1343 }
1344}
1345impl<Prev: Rec> PushArrayWgallowedip<Prev> {
1346 pub fn new(prev: Prev) -> Self {
1347 Self {
1348 prev: Some(prev),
1349 header_offset: None,
1350 counter: 0,
1351 }
1352 }
1353 pub fn end_array(mut self) -> Prev {
1354 let mut prev = self.prev.take().unwrap();
1355 if let Some(header_offset) = &self.header_offset {
1356 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1357 }
1358 prev
1359 }
1360 pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1361 let index = self.counter;
1362 self.counter += 1;
1363 let header_offset = push_nested_header(self.as_rec_mut(), index);
1364 PushWgallowedip {
1365 prev: Some(self),
1366 header_offset: Some(header_offset),
1367 }
1368 }
1369}
1370impl<Prev: Rec> Drop for PushArrayWgallowedip<Prev> {
1371 fn drop(&mut self) {
1372 if let Some(prev) = &mut self.prev {
1373 if let Some(header_offset) = &self.header_offset {
1374 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1375 }
1376 }
1377 }
1378}
1379impl<Prev: Rec> PushWgpeer<Prev> {
1380 pub fn new(prev: Prev) -> Self {
1381 Self {
1382 prev: Some(prev),
1383 header_offset: None,
1384 }
1385 }
1386 pub fn end_nested(mut self) -> Prev {
1387 let mut prev = self.prev.take().unwrap();
1388 if let Some(header_offset) = &self.header_offset {
1389 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1390 }
1391 prev
1392 }
1393 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1394 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
1395 self.as_rec_mut().extend(value);
1396 self
1397 }
1398 #[doc = "Set as all zeros to remove."]
1399 pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1400 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
1401 self.as_rec_mut().extend(value);
1402 self
1403 }
1404 #[doc = "0 and/or WGPEER_F_REMOVE_ME if the specified peer should not\nexist at the end of the operation, rather than added/updated\nand/or WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed IPs\nof this peer should be removed prior to adding the list below\nand/or WGPEER_F_UPDATE_ONLY if the peer should only be set if\nit already exists.\n\nAssociated type: \"WgpeerFlags\" (enum)"]
1405 pub fn push_flags(mut self, value: u32) -> Self {
1406 push_header(self.as_rec_mut(), 3u16, 4 as u16);
1407 self.as_rec_mut().extend(value.to_ne_bytes());
1408 self
1409 }
1410 #[doc = "struct sockaddr_in or struct sockaddr_in6"]
1411 pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1412 push_header(self.as_rec_mut(), 4u16, {
1413 match &value {
1414 SocketAddr::V4(_) => 16,
1415 SocketAddr::V6(_) => 28,
1416 }
1417 } as u16);
1418 encode_sockaddr(self.as_rec_mut(), value);
1419 self
1420 }
1421 #[doc = "Set as 0 to disable."]
1422 pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1423 push_header(self.as_rec_mut(), 5u16, 2 as u16);
1424 self.as_rec_mut().extend(value.to_ne_bytes());
1425 self
1426 }
1427 pub fn push_last_handshake_time(mut self, value: PushKernelTimespec) -> Self {
1428 push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
1429 self.as_rec_mut().extend(value.as_slice());
1430 self
1431 }
1432 pub fn push_rx_bytes(mut self, value: u64) -> Self {
1433 push_header(self.as_rec_mut(), 7u16, 8 as u16);
1434 self.as_rec_mut().extend(value.to_ne_bytes());
1435 self
1436 }
1437 pub fn push_tx_bytes(mut self, value: u64) -> Self {
1438 push_header(self.as_rec_mut(), 8u16, 8 as u16);
1439 self.as_rec_mut().extend(value.to_ne_bytes());
1440 self
1441 }
1442 pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1443 let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
1444 PushArrayWgallowedip {
1445 prev: Some(self),
1446 header_offset: Some(header_offset),
1447 counter: 0,
1448 }
1449 }
1450 #[doc = "should not be set or used at all by most users of this API,\nas the most recent protocol will be used when this is unset.\nOtherwise, must be set to 1.\n"]
1451 pub fn push_protocol_version(mut self, value: u32) -> Self {
1452 push_header(self.as_rec_mut(), 10u16, 4 as u16);
1453 self.as_rec_mut().extend(value.to_ne_bytes());
1454 self
1455 }
1456}
1457impl<Prev: Rec> Drop for PushWgpeer<Prev> {
1458 fn drop(&mut self) {
1459 if let Some(prev) = &mut self.prev {
1460 if let Some(header_offset) = &self.header_offset {
1461 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1462 }
1463 }
1464 }
1465}
1466pub struct PushWgallowedip<Prev: Rec> {
1467 pub(crate) prev: Option<Prev>,
1468 pub(crate) header_offset: Option<usize>,
1469}
1470impl<Prev: Rec> Rec for PushWgallowedip<Prev> {
1471 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1472 self.prev.as_mut().unwrap().as_rec_mut()
1473 }
1474}
1475impl<Prev: Rec> PushWgallowedip<Prev> {
1476 pub fn new(prev: Prev) -> Self {
1477 Self {
1478 prev: Some(prev),
1479 header_offset: None,
1480 }
1481 }
1482 pub fn end_nested(mut self) -> Prev {
1483 let mut prev = self.prev.take().unwrap();
1484 if let Some(header_offset) = &self.header_offset {
1485 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1486 }
1487 prev
1488 }
1489 pub fn push_family(mut self, value: u16) -> Self {
1490 push_header(self.as_rec_mut(), 1u16, 2 as u16);
1491 self.as_rec_mut().extend(value.to_ne_bytes());
1492 self
1493 }
1494 #[doc = "struct in_addr or struct in6_add"]
1495 pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1496 push_header(self.as_rec_mut(), 2u16, {
1497 match &value {
1498 IpAddr::V4(_) => 4,
1499 IpAddr::V6(_) => 16,
1500 }
1501 } as u16);
1502 encode_ip(self.as_rec_mut(), value);
1503 self
1504 }
1505 pub fn push_cidr_mask(mut self, value: u8) -> Self {
1506 push_header(self.as_rec_mut(), 3u16, 1 as u16);
1507 self.as_rec_mut().extend(value.to_ne_bytes());
1508 self
1509 }
1510 #[doc = "WGALLOWEDIP_F_REMOVE_ME if the specified IP should be removed;\notherwise, this IP will be added if it is not already present.\n\nAssociated type: \"WgallowedipFlags\" (enum)"]
1511 pub fn push_flags(mut self, value: u32) -> Self {
1512 push_header(self.as_rec_mut(), 4u16, 4 as u16);
1513 self.as_rec_mut().extend(value.to_ne_bytes());
1514 self
1515 }
1516}
1517impl<Prev: Rec> Drop for PushWgallowedip<Prev> {
1518 fn drop(&mut self) {
1519 if let Some(prev) = &mut self.prev {
1520 if let Some(header_offset) = &self.header_offset {
1521 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1522 }
1523 }
1524 }
1525}
1526#[derive(Clone)]
1527pub struct PushKernelTimespec {
1528 pub(crate) buf: [u8; 16usize],
1529}
1530#[doc = "Create zero-initialized struct"]
1531impl Default for PushKernelTimespec {
1532 fn default() -> Self {
1533 Self {
1534 buf: [0u8; 16usize],
1535 }
1536 }
1537}
1538impl PushKernelTimespec {
1539 #[doc = "Create zero-initialized struct"]
1540 pub fn new() -> Self {
1541 Default::default()
1542 }
1543 #[doc = "Copy from contents from other slice"]
1544 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
1545 if other.len() != Self::len() {
1546 return None;
1547 }
1548 let mut buf = [0u8; Self::len()];
1549 buf.clone_from_slice(other);
1550 Some(Self { buf })
1551 }
1552 pub fn as_slice(&self) -> &[u8] {
1553 &self.buf
1554 }
1555 pub fn as_mut_slice(&mut self) -> &mut [u8] {
1556 &mut self.buf
1557 }
1558 pub const fn len() -> usize {
1559 16usize
1560 }
1561 #[doc = "Number of seconds, since UNIX epoch."]
1562 pub fn sec(&self) -> u64 {
1563 parse_u64(&self.buf[0usize..8usize]).unwrap()
1564 }
1565 #[doc = "Number of seconds, since UNIX epoch."]
1566 pub fn set_sec(&mut self, value: u64) {
1567 self.buf[0usize..8usize].copy_from_slice(&value.to_ne_bytes())
1568 }
1569 #[doc = "Number of nanoseconds, after the second began."]
1570 pub fn nsec(&self) -> u64 {
1571 parse_u64(&self.buf[8usize..16usize]).unwrap()
1572 }
1573 #[doc = "Number of nanoseconds, after the second began."]
1574 pub fn set_nsec(&mut self, value: u64) {
1575 self.buf[8usize..16usize].copy_from_slice(&value.to_ne_bytes())
1576 }
1577}
1578impl std::fmt::Debug for PushKernelTimespec {
1579 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1580 fmt.debug_struct("KernelTimespec")
1581 .field("sec", &self.sec())
1582 .field("nsec", &self.nsec())
1583 .finish()
1584 }
1585}
1586#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce adjacent peers. Likewise, it is possible that all peers will\nnot fit within a single message. So, subsequent peers will be sent\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
1587pub struct PushOpGetDeviceDumpRequest<Prev: Rec> {
1588 pub(crate) prev: Option<Prev>,
1589 pub(crate) header_offset: Option<usize>,
1590}
1591impl<Prev: Rec> Rec for PushOpGetDeviceDumpRequest<Prev> {
1592 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1593 self.prev.as_mut().unwrap().as_rec_mut()
1594 }
1595}
1596impl<Prev: Rec> PushOpGetDeviceDumpRequest<Prev> {
1597 pub fn new(mut prev: Prev) -> Self {
1598 Self::write_header(&mut prev);
1599 Self::new_without_header(prev)
1600 }
1601 fn new_without_header(prev: Prev) -> Self {
1602 Self {
1603 prev: Some(prev),
1604 header_offset: None,
1605 }
1606 }
1607 fn write_header(prev: &mut Prev) {
1608 let mut header = PushBuiltinNfgenmsg::new();
1609 header.set_cmd(0u8);
1610 header.set_version(1u8);
1611 prev.as_rec_mut().extend(header.as_slice());
1612 }
1613 pub fn end_nested(mut self) -> Prev {
1614 let mut prev = self.prev.take().unwrap();
1615 if let Some(header_offset) = &self.header_offset {
1616 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1617 }
1618 prev
1619 }
1620 pub fn push_ifindex(mut self, value: u32) -> Self {
1621 push_header(self.as_rec_mut(), 1u16, 4 as u16);
1622 self.as_rec_mut().extend(value.to_ne_bytes());
1623 self
1624 }
1625 pub fn push_ifname(mut self, value: &CStr) -> Self {
1626 push_header(
1627 self.as_rec_mut(),
1628 2u16,
1629 value.to_bytes_with_nul().len() as u16,
1630 );
1631 self.as_rec_mut().extend(value.to_bytes_with_nul());
1632 self
1633 }
1634 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1635 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1636 self.as_rec_mut().extend(value);
1637 self.as_rec_mut().push(0);
1638 self
1639 }
1640 #[doc = "Set to all zeros to remove."]
1641 pub fn push_private_key(mut self, value: &[u8]) -> Self {
1642 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1643 self.as_rec_mut().extend(value);
1644 self
1645 }
1646 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1647 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1648 self.as_rec_mut().extend(value);
1649 self
1650 }
1651 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1652 pub fn push_flags(mut self, value: u32) -> Self {
1653 push_header(self.as_rec_mut(), 5u16, 4 as u16);
1654 self.as_rec_mut().extend(value.to_ne_bytes());
1655 self
1656 }
1657 #[doc = "Set as 0 to choose randomly."]
1658 pub fn push_listen_port(mut self, value: u16) -> Self {
1659 push_header(self.as_rec_mut(), 6u16, 2 as u16);
1660 self.as_rec_mut().extend(value.to_ne_bytes());
1661 self
1662 }
1663 #[doc = "Set as 0 to disable."]
1664 pub fn push_fwmark(mut self, value: u32) -> Self {
1665 push_header(self.as_rec_mut(), 7u16, 4 as u16);
1666 self.as_rec_mut().extend(value.to_ne_bytes());
1667 self
1668 }
1669 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1670 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1671 PushArrayWgpeer {
1672 prev: Some(self),
1673 header_offset: Some(header_offset),
1674 counter: 0,
1675 }
1676 }
1677}
1678impl<Prev: Rec> Drop for PushOpGetDeviceDumpRequest<Prev> {
1679 fn drop(&mut self) {
1680 if let Some(prev) = &mut self.prev {
1681 if let Some(header_offset) = &self.header_offset {
1682 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1683 }
1684 }
1685 }
1686}
1687#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce adjacent peers. Likewise, it is possible that all peers will\nnot fit within a single message. So, subsequent peers will be sent\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
1688#[derive(Clone)]
1689pub enum OpGetDeviceDumpRequest<'a> {
1690 Ifindex(u32),
1691 Ifname(&'a CStr),
1692 #[doc = "Set to all zeros to remove."]
1693 PrivateKey(&'a [u8]),
1694 PublicKey(&'a [u8]),
1695 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1696 Flags(u32),
1697 #[doc = "Set as 0 to choose randomly."]
1698 ListenPort(u16),
1699 #[doc = "Set as 0 to disable."]
1700 Fwmark(u32),
1701 Peers(IterableArrayWgpeer<'a>),
1702}
1703impl<'a> IterableOpGetDeviceDumpRequest<'a> {
1704 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1705 let mut iter = self.clone();
1706 iter.pos = 0;
1707 for attr in iter {
1708 if let OpGetDeviceDumpRequest::Ifindex(val) = attr? {
1709 return Ok(val);
1710 }
1711 }
1712 Err(ErrorContext::new_missing(
1713 "OpGetDeviceDumpRequest",
1714 "Ifindex",
1715 self.orig_loc,
1716 self.buf.as_ptr() as usize,
1717 ))
1718 }
1719 pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
1720 let mut iter = self.clone();
1721 iter.pos = 0;
1722 for attr in iter {
1723 if let OpGetDeviceDumpRequest::Ifname(val) = attr? {
1724 return Ok(val);
1725 }
1726 }
1727 Err(ErrorContext::new_missing(
1728 "OpGetDeviceDumpRequest",
1729 "Ifname",
1730 self.orig_loc,
1731 self.buf.as_ptr() as usize,
1732 ))
1733 }
1734 #[doc = "Set to all zeros to remove."]
1735 pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
1736 let mut iter = self.clone();
1737 iter.pos = 0;
1738 for attr in iter {
1739 if let OpGetDeviceDumpRequest::PrivateKey(val) = attr? {
1740 return Ok(val);
1741 }
1742 }
1743 Err(ErrorContext::new_missing(
1744 "OpGetDeviceDumpRequest",
1745 "PrivateKey",
1746 self.orig_loc,
1747 self.buf.as_ptr() as usize,
1748 ))
1749 }
1750 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
1751 let mut iter = self.clone();
1752 iter.pos = 0;
1753 for attr in iter {
1754 if let OpGetDeviceDumpRequest::PublicKey(val) = attr? {
1755 return Ok(val);
1756 }
1757 }
1758 Err(ErrorContext::new_missing(
1759 "OpGetDeviceDumpRequest",
1760 "PublicKey",
1761 self.orig_loc,
1762 self.buf.as_ptr() as usize,
1763 ))
1764 }
1765 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
1766 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1767 let mut iter = self.clone();
1768 iter.pos = 0;
1769 for attr in iter {
1770 if let OpGetDeviceDumpRequest::Flags(val) = attr? {
1771 return Ok(val);
1772 }
1773 }
1774 Err(ErrorContext::new_missing(
1775 "OpGetDeviceDumpRequest",
1776 "Flags",
1777 self.orig_loc,
1778 self.buf.as_ptr() as usize,
1779 ))
1780 }
1781 #[doc = "Set as 0 to choose randomly."]
1782 pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
1783 let mut iter = self.clone();
1784 iter.pos = 0;
1785 for attr in iter {
1786 if let OpGetDeviceDumpRequest::ListenPort(val) = attr? {
1787 return Ok(val);
1788 }
1789 }
1790 Err(ErrorContext::new_missing(
1791 "OpGetDeviceDumpRequest",
1792 "ListenPort",
1793 self.orig_loc,
1794 self.buf.as_ptr() as usize,
1795 ))
1796 }
1797 #[doc = "Set as 0 to disable."]
1798 pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
1799 let mut iter = self.clone();
1800 iter.pos = 0;
1801 for attr in iter {
1802 if let OpGetDeviceDumpRequest::Fwmark(val) = attr? {
1803 return Ok(val);
1804 }
1805 }
1806 Err(ErrorContext::new_missing(
1807 "OpGetDeviceDumpRequest",
1808 "Fwmark",
1809 self.orig_loc,
1810 self.buf.as_ptr() as usize,
1811 ))
1812 }
1813 pub fn get_peers(
1814 &self,
1815 ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
1816 for attr in self.clone() {
1817 if let OpGetDeviceDumpRequest::Peers(val) = attr? {
1818 return Ok(ArrayIterable::new(val));
1819 }
1820 }
1821 Err(ErrorContext::new_missing(
1822 "OpGetDeviceDumpRequest",
1823 "Peers",
1824 self.orig_loc,
1825 self.buf.as_ptr() as usize,
1826 ))
1827 }
1828}
1829impl<'a> OpGetDeviceDumpRequest<'a> {
1830 pub fn new(buf: &'a [u8]) -> IterableOpGetDeviceDumpRequest<'a> {
1831 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
1832 IterableOpGetDeviceDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
1833 }
1834 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1835 Wgdevice::attr_from_type(r#type)
1836 }
1837}
1838#[derive(Clone, Copy, Default)]
1839pub struct IterableOpGetDeviceDumpRequest<'a> {
1840 buf: &'a [u8],
1841 pos: usize,
1842 orig_loc: usize,
1843}
1844impl<'a> IterableOpGetDeviceDumpRequest<'a> {
1845 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1846 Self {
1847 buf,
1848 pos: 0,
1849 orig_loc,
1850 }
1851 }
1852 pub fn get_buf(&self) -> &'a [u8] {
1853 self.buf
1854 }
1855}
1856impl<'a> Iterator for IterableOpGetDeviceDumpRequest<'a> {
1857 type Item = Result<OpGetDeviceDumpRequest<'a>, ErrorContext>;
1858 fn next(&mut self) -> Option<Self::Item> {
1859 if self.buf.len() == self.pos {
1860 return None;
1861 }
1862 let pos = self.pos;
1863 let mut r#type = None;
1864 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1865 r#type = Some(header.r#type);
1866 let res = match header.r#type {
1867 1u16 => OpGetDeviceDumpRequest::Ifindex({
1868 let res = parse_u32(next);
1869 let Some(val) = res else { break };
1870 val
1871 }),
1872 2u16 => OpGetDeviceDumpRequest::Ifname({
1873 let res = CStr::from_bytes_with_nul(next).ok();
1874 let Some(val) = res else { break };
1875 val
1876 }),
1877 3u16 => OpGetDeviceDumpRequest::PrivateKey({
1878 let res = Some(next);
1879 let Some(val) = res else { break };
1880 val
1881 }),
1882 4u16 => OpGetDeviceDumpRequest::PublicKey({
1883 let res = Some(next);
1884 let Some(val) = res else { break };
1885 val
1886 }),
1887 5u16 => OpGetDeviceDumpRequest::Flags({
1888 let res = parse_u32(next);
1889 let Some(val) = res else { break };
1890 val
1891 }),
1892 6u16 => OpGetDeviceDumpRequest::ListenPort({
1893 let res = parse_u16(next);
1894 let Some(val) = res else { break };
1895 val
1896 }),
1897 7u16 => OpGetDeviceDumpRequest::Fwmark({
1898 let res = parse_u32(next);
1899 let Some(val) = res else { break };
1900 val
1901 }),
1902 8u16 => OpGetDeviceDumpRequest::Peers({
1903 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
1904 let Some(val) = res else { break };
1905 val
1906 }),
1907 n => {
1908 if cfg!(any(test, feature = "deny-unknown-attrs")) {
1909 break;
1910 } else {
1911 continue;
1912 }
1913 }
1914 };
1915 return Some(Ok(res));
1916 }
1917 Some(Err(ErrorContext::new(
1918 "OpGetDeviceDumpRequest",
1919 r#type.and_then(|t| OpGetDeviceDumpRequest::attr_from_type(t)),
1920 self.orig_loc,
1921 self.buf.as_ptr().wrapping_add(pos) as usize,
1922 )))
1923 }
1924}
1925impl<'a> std::fmt::Debug for IterableOpGetDeviceDumpRequest<'_> {
1926 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1927 let mut fmt = f.debug_struct("OpGetDeviceDumpRequest");
1928 for attr in self.clone() {
1929 let attr = match attr {
1930 Ok(a) => a,
1931 Err(err) => {
1932 fmt.finish()?;
1933 f.write_str("Err(")?;
1934 err.fmt(f)?;
1935 return f.write_str(")");
1936 }
1937 };
1938 match attr {
1939 OpGetDeviceDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
1940 OpGetDeviceDumpRequest::Ifname(val) => fmt.field("Ifname", &val),
1941 OpGetDeviceDumpRequest::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
1942 OpGetDeviceDumpRequest::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
1943 OpGetDeviceDumpRequest::Flags(val) => {
1944 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
1945 }
1946 OpGetDeviceDumpRequest::ListenPort(val) => fmt.field("ListenPort", &val),
1947 OpGetDeviceDumpRequest::Fwmark(val) => fmt.field("Fwmark", &val),
1948 OpGetDeviceDumpRequest::Peers(val) => fmt.field("Peers", &val),
1949 };
1950 }
1951 fmt.finish()
1952 }
1953}
1954impl IterableOpGetDeviceDumpRequest<'_> {
1955 pub fn lookup_attr(
1956 &self,
1957 offset: usize,
1958 missing_type: Option<u16>,
1959 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1960 let mut stack = Vec::new();
1961 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1962 if cur == offset + PushBuiltinNfgenmsg::len() {
1963 stack.push(("OpGetDeviceDumpRequest", offset));
1964 return (
1965 stack,
1966 missing_type.and_then(|t| OpGetDeviceDumpRequest::attr_from_type(t)),
1967 );
1968 }
1969 if cur > offset || cur + self.buf.len() < offset {
1970 return (stack, None);
1971 }
1972 let mut attrs = self.clone();
1973 let mut last_off = cur + attrs.pos;
1974 let mut missing = None;
1975 while let Some(attr) = attrs.next() {
1976 let Ok(attr) = attr else { break };
1977 match attr {
1978 OpGetDeviceDumpRequest::Ifindex(val) => {
1979 if last_off == offset {
1980 stack.push(("Ifindex", last_off));
1981 break;
1982 }
1983 }
1984 OpGetDeviceDumpRequest::Ifname(val) => {
1985 if last_off == offset {
1986 stack.push(("Ifname", last_off));
1987 break;
1988 }
1989 }
1990 OpGetDeviceDumpRequest::PrivateKey(val) => {
1991 if last_off == offset {
1992 stack.push(("PrivateKey", last_off));
1993 break;
1994 }
1995 }
1996 OpGetDeviceDumpRequest::PublicKey(val) => {
1997 if last_off == offset {
1998 stack.push(("PublicKey", last_off));
1999 break;
2000 }
2001 }
2002 OpGetDeviceDumpRequest::Flags(val) => {
2003 if last_off == offset {
2004 stack.push(("Flags", last_off));
2005 break;
2006 }
2007 }
2008 OpGetDeviceDumpRequest::ListenPort(val) => {
2009 if last_off == offset {
2010 stack.push(("ListenPort", last_off));
2011 break;
2012 }
2013 }
2014 OpGetDeviceDumpRequest::Fwmark(val) => {
2015 if last_off == offset {
2016 stack.push(("Fwmark", last_off));
2017 break;
2018 }
2019 }
2020 OpGetDeviceDumpRequest::Peers(val) => {
2021 for entry in val {
2022 let Ok(attr) = entry else { break };
2023 (stack, missing) = attr.lookup_attr(offset, missing_type);
2024 if !stack.is_empty() {
2025 break;
2026 }
2027 }
2028 if !stack.is_empty() {
2029 stack.push(("Peers", last_off));
2030 break;
2031 }
2032 }
2033 _ => {}
2034 };
2035 last_off = cur + attrs.pos;
2036 }
2037 if !stack.is_empty() {
2038 stack.push(("OpGetDeviceDumpRequest", cur));
2039 }
2040 (stack, missing)
2041 }
2042}
2043#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce adjacent peers. Likewise, it is possible that all peers will\nnot fit within a single message. So, subsequent peers will be sent\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
2044pub struct PushOpGetDeviceDumpReply<Prev: Rec> {
2045 pub(crate) prev: Option<Prev>,
2046 pub(crate) header_offset: Option<usize>,
2047}
2048impl<Prev: Rec> Rec for PushOpGetDeviceDumpReply<Prev> {
2049 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2050 self.prev.as_mut().unwrap().as_rec_mut()
2051 }
2052}
2053impl<Prev: Rec> PushOpGetDeviceDumpReply<Prev> {
2054 pub fn new(mut prev: Prev) -> Self {
2055 Self::write_header(&mut prev);
2056 Self::new_without_header(prev)
2057 }
2058 fn new_without_header(prev: Prev) -> Self {
2059 Self {
2060 prev: Some(prev),
2061 header_offset: None,
2062 }
2063 }
2064 fn write_header(prev: &mut Prev) {
2065 let mut header = PushBuiltinNfgenmsg::new();
2066 header.set_cmd(0u8);
2067 header.set_version(1u8);
2068 prev.as_rec_mut().extend(header.as_slice());
2069 }
2070 pub fn end_nested(mut self) -> Prev {
2071 let mut prev = self.prev.take().unwrap();
2072 if let Some(header_offset) = &self.header_offset {
2073 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2074 }
2075 prev
2076 }
2077 pub fn push_ifindex(mut self, value: u32) -> Self {
2078 push_header(self.as_rec_mut(), 1u16, 4 as u16);
2079 self.as_rec_mut().extend(value.to_ne_bytes());
2080 self
2081 }
2082 pub fn push_ifname(mut self, value: &CStr) -> Self {
2083 push_header(
2084 self.as_rec_mut(),
2085 2u16,
2086 value.to_bytes_with_nul().len() as u16,
2087 );
2088 self.as_rec_mut().extend(value.to_bytes_with_nul());
2089 self
2090 }
2091 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
2092 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
2093 self.as_rec_mut().extend(value);
2094 self.as_rec_mut().push(0);
2095 self
2096 }
2097 #[doc = "Set to all zeros to remove."]
2098 pub fn push_private_key(mut self, value: &[u8]) -> Self {
2099 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
2100 self.as_rec_mut().extend(value);
2101 self
2102 }
2103 pub fn push_public_key(mut self, value: &[u8]) -> Self {
2104 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
2105 self.as_rec_mut().extend(value);
2106 self
2107 }
2108 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2109 pub fn push_flags(mut self, value: u32) -> Self {
2110 push_header(self.as_rec_mut(), 5u16, 4 as u16);
2111 self.as_rec_mut().extend(value.to_ne_bytes());
2112 self
2113 }
2114 #[doc = "Set as 0 to choose randomly."]
2115 pub fn push_listen_port(mut self, value: u16) -> Self {
2116 push_header(self.as_rec_mut(), 6u16, 2 as u16);
2117 self.as_rec_mut().extend(value.to_ne_bytes());
2118 self
2119 }
2120 #[doc = "Set as 0 to disable."]
2121 pub fn push_fwmark(mut self, value: u32) -> Self {
2122 push_header(self.as_rec_mut(), 7u16, 4 as u16);
2123 self.as_rec_mut().extend(value.to_ne_bytes());
2124 self
2125 }
2126 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
2127 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
2128 PushArrayWgpeer {
2129 prev: Some(self),
2130 header_offset: Some(header_offset),
2131 counter: 0,
2132 }
2133 }
2134}
2135impl<Prev: Rec> Drop for PushOpGetDeviceDumpReply<Prev> {
2136 fn drop(&mut self) {
2137 if let Some(prev) = &mut self.prev {
2138 if let Some(header_offset) = &self.header_offset {
2139 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2140 }
2141 }
2142 }
2143}
2144#[doc = "Retrieve WireGuard device.\n\nThe command should be called with one but not both of:\n* WGDEVICE_A_IFINDEX\n* WGDEVICE_A_IFNAME\n\nThe kernel will then return several messages (NLM_F_MULTI).\nIt is possible that all of the allowed IPs of a single peer will not\nfit within a single netlink message. In that case, the same peer will\nbe written in the following message, except it will only contain\nWGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several\ntimes in a row for the same peer. It is then up to the receiver to\ncoalesce adjacent peers. Likewise, it is possible that all peers will\nnot fit within a single message. So, subsequent peers will be sent\nin following messages, except those will only contain\nWGDEVICE_A_IFNAME and WGDEVICE_A_PEERS. It is then up to the receiver\nto coalesce these messages to form the complete list of peers.\n\nSince this is an NLA_F_DUMP command, the final message will always be\nNLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message\ncontains an integer error code. It is either zero or a negative error\ncode corresponding to the errno.\n"]
2145#[derive(Clone)]
2146pub enum OpGetDeviceDumpReply<'a> {
2147 Ifindex(u32),
2148 Ifname(&'a CStr),
2149 #[doc = "Set to all zeros to remove."]
2150 PrivateKey(&'a [u8]),
2151 PublicKey(&'a [u8]),
2152 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2153 Flags(u32),
2154 #[doc = "Set as 0 to choose randomly."]
2155 ListenPort(u16),
2156 #[doc = "Set as 0 to disable."]
2157 Fwmark(u32),
2158 Peers(IterableArrayWgpeer<'a>),
2159}
2160impl<'a> IterableOpGetDeviceDumpReply<'a> {
2161 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2162 let mut iter = self.clone();
2163 iter.pos = 0;
2164 for attr in iter {
2165 if let OpGetDeviceDumpReply::Ifindex(val) = attr? {
2166 return Ok(val);
2167 }
2168 }
2169 Err(ErrorContext::new_missing(
2170 "OpGetDeviceDumpReply",
2171 "Ifindex",
2172 self.orig_loc,
2173 self.buf.as_ptr() as usize,
2174 ))
2175 }
2176 pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
2177 let mut iter = self.clone();
2178 iter.pos = 0;
2179 for attr in iter {
2180 if let OpGetDeviceDumpReply::Ifname(val) = attr? {
2181 return Ok(val);
2182 }
2183 }
2184 Err(ErrorContext::new_missing(
2185 "OpGetDeviceDumpReply",
2186 "Ifname",
2187 self.orig_loc,
2188 self.buf.as_ptr() as usize,
2189 ))
2190 }
2191 #[doc = "Set to all zeros to remove."]
2192 pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
2193 let mut iter = self.clone();
2194 iter.pos = 0;
2195 for attr in iter {
2196 if let OpGetDeviceDumpReply::PrivateKey(val) = attr? {
2197 return Ok(val);
2198 }
2199 }
2200 Err(ErrorContext::new_missing(
2201 "OpGetDeviceDumpReply",
2202 "PrivateKey",
2203 self.orig_loc,
2204 self.buf.as_ptr() as usize,
2205 ))
2206 }
2207 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
2208 let mut iter = self.clone();
2209 iter.pos = 0;
2210 for attr in iter {
2211 if let OpGetDeviceDumpReply::PublicKey(val) = attr? {
2212 return Ok(val);
2213 }
2214 }
2215 Err(ErrorContext::new_missing(
2216 "OpGetDeviceDumpReply",
2217 "PublicKey",
2218 self.orig_loc,
2219 self.buf.as_ptr() as usize,
2220 ))
2221 }
2222 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2223 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
2224 let mut iter = self.clone();
2225 iter.pos = 0;
2226 for attr in iter {
2227 if let OpGetDeviceDumpReply::Flags(val) = attr? {
2228 return Ok(val);
2229 }
2230 }
2231 Err(ErrorContext::new_missing(
2232 "OpGetDeviceDumpReply",
2233 "Flags",
2234 self.orig_loc,
2235 self.buf.as_ptr() as usize,
2236 ))
2237 }
2238 #[doc = "Set as 0 to choose randomly."]
2239 pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
2240 let mut iter = self.clone();
2241 iter.pos = 0;
2242 for attr in iter {
2243 if let OpGetDeviceDumpReply::ListenPort(val) = attr? {
2244 return Ok(val);
2245 }
2246 }
2247 Err(ErrorContext::new_missing(
2248 "OpGetDeviceDumpReply",
2249 "ListenPort",
2250 self.orig_loc,
2251 self.buf.as_ptr() as usize,
2252 ))
2253 }
2254 #[doc = "Set as 0 to disable."]
2255 pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
2256 let mut iter = self.clone();
2257 iter.pos = 0;
2258 for attr in iter {
2259 if let OpGetDeviceDumpReply::Fwmark(val) = attr? {
2260 return Ok(val);
2261 }
2262 }
2263 Err(ErrorContext::new_missing(
2264 "OpGetDeviceDumpReply",
2265 "Fwmark",
2266 self.orig_loc,
2267 self.buf.as_ptr() as usize,
2268 ))
2269 }
2270 pub fn get_peers(
2271 &self,
2272 ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
2273 for attr in self.clone() {
2274 if let OpGetDeviceDumpReply::Peers(val) = attr? {
2275 return Ok(ArrayIterable::new(val));
2276 }
2277 }
2278 Err(ErrorContext::new_missing(
2279 "OpGetDeviceDumpReply",
2280 "Peers",
2281 self.orig_loc,
2282 self.buf.as_ptr() as usize,
2283 ))
2284 }
2285}
2286impl<'a> OpGetDeviceDumpReply<'a> {
2287 pub fn new(buf: &'a [u8]) -> IterableOpGetDeviceDumpReply<'a> {
2288 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
2289 IterableOpGetDeviceDumpReply::with_loc(attrs, buf.as_ptr() as usize)
2290 }
2291 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2292 Wgdevice::attr_from_type(r#type)
2293 }
2294}
2295#[derive(Clone, Copy, Default)]
2296pub struct IterableOpGetDeviceDumpReply<'a> {
2297 buf: &'a [u8],
2298 pos: usize,
2299 orig_loc: usize,
2300}
2301impl<'a> IterableOpGetDeviceDumpReply<'a> {
2302 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2303 Self {
2304 buf,
2305 pos: 0,
2306 orig_loc,
2307 }
2308 }
2309 pub fn get_buf(&self) -> &'a [u8] {
2310 self.buf
2311 }
2312}
2313impl<'a> Iterator for IterableOpGetDeviceDumpReply<'a> {
2314 type Item = Result<OpGetDeviceDumpReply<'a>, ErrorContext>;
2315 fn next(&mut self) -> Option<Self::Item> {
2316 if self.buf.len() == self.pos {
2317 return None;
2318 }
2319 let pos = self.pos;
2320 let mut r#type = None;
2321 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2322 r#type = Some(header.r#type);
2323 let res = match header.r#type {
2324 1u16 => OpGetDeviceDumpReply::Ifindex({
2325 let res = parse_u32(next);
2326 let Some(val) = res else { break };
2327 val
2328 }),
2329 2u16 => OpGetDeviceDumpReply::Ifname({
2330 let res = CStr::from_bytes_with_nul(next).ok();
2331 let Some(val) = res else { break };
2332 val
2333 }),
2334 3u16 => OpGetDeviceDumpReply::PrivateKey({
2335 let res = Some(next);
2336 let Some(val) = res else { break };
2337 val
2338 }),
2339 4u16 => OpGetDeviceDumpReply::PublicKey({
2340 let res = Some(next);
2341 let Some(val) = res else { break };
2342 val
2343 }),
2344 5u16 => OpGetDeviceDumpReply::Flags({
2345 let res = parse_u32(next);
2346 let Some(val) = res else { break };
2347 val
2348 }),
2349 6u16 => OpGetDeviceDumpReply::ListenPort({
2350 let res = parse_u16(next);
2351 let Some(val) = res else { break };
2352 val
2353 }),
2354 7u16 => OpGetDeviceDumpReply::Fwmark({
2355 let res = parse_u32(next);
2356 let Some(val) = res else { break };
2357 val
2358 }),
2359 8u16 => OpGetDeviceDumpReply::Peers({
2360 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
2361 let Some(val) = res else { break };
2362 val
2363 }),
2364 n => {
2365 if cfg!(any(test, feature = "deny-unknown-attrs")) {
2366 break;
2367 } else {
2368 continue;
2369 }
2370 }
2371 };
2372 return Some(Ok(res));
2373 }
2374 Some(Err(ErrorContext::new(
2375 "OpGetDeviceDumpReply",
2376 r#type.and_then(|t| OpGetDeviceDumpReply::attr_from_type(t)),
2377 self.orig_loc,
2378 self.buf.as_ptr().wrapping_add(pos) as usize,
2379 )))
2380 }
2381}
2382impl<'a> std::fmt::Debug for IterableOpGetDeviceDumpReply<'_> {
2383 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2384 let mut fmt = f.debug_struct("OpGetDeviceDumpReply");
2385 for attr in self.clone() {
2386 let attr = match attr {
2387 Ok(a) => a,
2388 Err(err) => {
2389 fmt.finish()?;
2390 f.write_str("Err(")?;
2391 err.fmt(f)?;
2392 return f.write_str(")");
2393 }
2394 };
2395 match attr {
2396 OpGetDeviceDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
2397 OpGetDeviceDumpReply::Ifname(val) => fmt.field("Ifname", &val),
2398 OpGetDeviceDumpReply::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
2399 OpGetDeviceDumpReply::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
2400 OpGetDeviceDumpReply::Flags(val) => {
2401 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
2402 }
2403 OpGetDeviceDumpReply::ListenPort(val) => fmt.field("ListenPort", &val),
2404 OpGetDeviceDumpReply::Fwmark(val) => fmt.field("Fwmark", &val),
2405 OpGetDeviceDumpReply::Peers(val) => fmt.field("Peers", &val),
2406 };
2407 }
2408 fmt.finish()
2409 }
2410}
2411impl IterableOpGetDeviceDumpReply<'_> {
2412 pub fn lookup_attr(
2413 &self,
2414 offset: usize,
2415 missing_type: Option<u16>,
2416 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2417 let mut stack = Vec::new();
2418 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2419 if cur == offset + PushBuiltinNfgenmsg::len() {
2420 stack.push(("OpGetDeviceDumpReply", offset));
2421 return (
2422 stack,
2423 missing_type.and_then(|t| OpGetDeviceDumpReply::attr_from_type(t)),
2424 );
2425 }
2426 if cur > offset || cur + self.buf.len() < offset {
2427 return (stack, None);
2428 }
2429 let mut attrs = self.clone();
2430 let mut last_off = cur + attrs.pos;
2431 let mut missing = None;
2432 while let Some(attr) = attrs.next() {
2433 let Ok(attr) = attr else { break };
2434 match attr {
2435 OpGetDeviceDumpReply::Ifindex(val) => {
2436 if last_off == offset {
2437 stack.push(("Ifindex", last_off));
2438 break;
2439 }
2440 }
2441 OpGetDeviceDumpReply::Ifname(val) => {
2442 if last_off == offset {
2443 stack.push(("Ifname", last_off));
2444 break;
2445 }
2446 }
2447 OpGetDeviceDumpReply::PrivateKey(val) => {
2448 if last_off == offset {
2449 stack.push(("PrivateKey", last_off));
2450 break;
2451 }
2452 }
2453 OpGetDeviceDumpReply::PublicKey(val) => {
2454 if last_off == offset {
2455 stack.push(("PublicKey", last_off));
2456 break;
2457 }
2458 }
2459 OpGetDeviceDumpReply::Flags(val) => {
2460 if last_off == offset {
2461 stack.push(("Flags", last_off));
2462 break;
2463 }
2464 }
2465 OpGetDeviceDumpReply::ListenPort(val) => {
2466 if last_off == offset {
2467 stack.push(("ListenPort", last_off));
2468 break;
2469 }
2470 }
2471 OpGetDeviceDumpReply::Fwmark(val) => {
2472 if last_off == offset {
2473 stack.push(("Fwmark", last_off));
2474 break;
2475 }
2476 }
2477 OpGetDeviceDumpReply::Peers(val) => {
2478 for entry in val {
2479 let Ok(attr) = entry else { break };
2480 (stack, missing) = attr.lookup_attr(offset, missing_type);
2481 if !stack.is_empty() {
2482 break;
2483 }
2484 }
2485 if !stack.is_empty() {
2486 stack.push(("Peers", last_off));
2487 break;
2488 }
2489 }
2490 _ => {}
2491 };
2492 last_off = cur + attrs.pos;
2493 }
2494 if !stack.is_empty() {
2495 stack.push(("OpGetDeviceDumpReply", cur));
2496 }
2497 (stack, missing)
2498 }
2499}
2500#[derive(Debug)]
2501pub struct RequestOpGetDeviceDumpRequest<'r> {
2502 request: Request<'r>,
2503}
2504impl<'r> RequestOpGetDeviceDumpRequest<'r> {
2505 pub fn new(mut request: Request<'r>) -> Self {
2506 PushOpGetDeviceDumpRequest::write_header(&mut request.buf_mut());
2507 Self {
2508 request: request.set_dump(),
2509 }
2510 }
2511 pub fn encode(&mut self) -> PushOpGetDeviceDumpRequest<&mut Vec<u8>> {
2512 PushOpGetDeviceDumpRequest::new_without_header(self.request.buf_mut())
2513 }
2514 pub fn into_encoder(self) -> PushOpGetDeviceDumpRequest<RequestBuf<'r>> {
2515 PushOpGetDeviceDumpRequest::new_without_header(self.request.buf)
2516 }
2517}
2518impl NetlinkRequest for RequestOpGetDeviceDumpRequest<'_> {
2519 type ReplyType<'buf> = IterableOpGetDeviceDumpReply<'buf>;
2520 fn protocol(&self) -> Protocol {
2521 Protocol::Generic("wireguard".as_bytes())
2522 }
2523 fn flags(&self) -> u16 {
2524 self.request.flags
2525 }
2526 fn payload(&self) -> &[u8] {
2527 self.request.buf()
2528 }
2529 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
2530 OpGetDeviceDumpReply::new(buf)
2531 }
2532 fn lookup(
2533 buf: &[u8],
2534 offset: usize,
2535 missing_type: Option<u16>,
2536 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2537 OpGetDeviceDumpRequest::new(buf).lookup_attr(offset, missing_type)
2538 }
2539}
2540#[doc = "Set WireGuard device.\n\nThis command should be called with a wgdevice set, containing one but\nnot both of WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME.\n\nIt is possible that the amount of configuration data exceeds that of\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended after.\nLikewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments.\n\nIf an error occurs, NLMSG_ERROR will reply containing an errno.\n"]
2541pub struct PushOpSetDeviceDoRequest<Prev: Rec> {
2542 pub(crate) prev: Option<Prev>,
2543 pub(crate) header_offset: Option<usize>,
2544}
2545impl<Prev: Rec> Rec for PushOpSetDeviceDoRequest<Prev> {
2546 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
2547 self.prev.as_mut().unwrap().as_rec_mut()
2548 }
2549}
2550impl<Prev: Rec> PushOpSetDeviceDoRequest<Prev> {
2551 pub fn new(mut prev: Prev) -> Self {
2552 Self::write_header(&mut prev);
2553 Self::new_without_header(prev)
2554 }
2555 fn new_without_header(prev: Prev) -> Self {
2556 Self {
2557 prev: Some(prev),
2558 header_offset: None,
2559 }
2560 }
2561 fn write_header(prev: &mut Prev) {
2562 let mut header = PushBuiltinNfgenmsg::new();
2563 header.set_cmd(1u8);
2564 header.set_version(1u8);
2565 prev.as_rec_mut().extend(header.as_slice());
2566 }
2567 pub fn end_nested(mut self) -> Prev {
2568 let mut prev = self.prev.take().unwrap();
2569 if let Some(header_offset) = &self.header_offset {
2570 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2571 }
2572 prev
2573 }
2574 pub fn push_ifindex(mut self, value: u32) -> Self {
2575 push_header(self.as_rec_mut(), 1u16, 4 as u16);
2576 self.as_rec_mut().extend(value.to_ne_bytes());
2577 self
2578 }
2579 pub fn push_ifname(mut self, value: &CStr) -> Self {
2580 push_header(
2581 self.as_rec_mut(),
2582 2u16,
2583 value.to_bytes_with_nul().len() as u16,
2584 );
2585 self.as_rec_mut().extend(value.to_bytes_with_nul());
2586 self
2587 }
2588 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
2589 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
2590 self.as_rec_mut().extend(value);
2591 self.as_rec_mut().push(0);
2592 self
2593 }
2594 #[doc = "Set to all zeros to remove."]
2595 pub fn push_private_key(mut self, value: &[u8]) -> Self {
2596 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
2597 self.as_rec_mut().extend(value);
2598 self
2599 }
2600 pub fn push_public_key(mut self, value: &[u8]) -> Self {
2601 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
2602 self.as_rec_mut().extend(value);
2603 self
2604 }
2605 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2606 pub fn push_flags(mut self, value: u32) -> Self {
2607 push_header(self.as_rec_mut(), 5u16, 4 as u16);
2608 self.as_rec_mut().extend(value.to_ne_bytes());
2609 self
2610 }
2611 #[doc = "Set as 0 to choose randomly."]
2612 pub fn push_listen_port(mut self, value: u16) -> Self {
2613 push_header(self.as_rec_mut(), 6u16, 2 as u16);
2614 self.as_rec_mut().extend(value.to_ne_bytes());
2615 self
2616 }
2617 #[doc = "Set as 0 to disable."]
2618 pub fn push_fwmark(mut self, value: u32) -> Self {
2619 push_header(self.as_rec_mut(), 7u16, 4 as u16);
2620 self.as_rec_mut().extend(value.to_ne_bytes());
2621 self
2622 }
2623 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
2624 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
2625 PushArrayWgpeer {
2626 prev: Some(self),
2627 header_offset: Some(header_offset),
2628 counter: 0,
2629 }
2630 }
2631}
2632impl<Prev: Rec> Drop for PushOpSetDeviceDoRequest<Prev> {
2633 fn drop(&mut self) {
2634 if let Some(prev) = &mut self.prev {
2635 if let Some(header_offset) = &self.header_offset {
2636 finalize_nested_header(prev.as_rec_mut(), *header_offset);
2637 }
2638 }
2639 }
2640}
2641#[doc = "Set WireGuard device.\n\nThis command should be called with a wgdevice set, containing one but\nnot both of WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME.\n\nIt is possible that the amount of configuration data exceeds that of\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended after.\nLikewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments.\n\nIf an error occurs, NLMSG_ERROR will reply containing an errno.\n"]
2642#[derive(Clone)]
2643pub enum OpSetDeviceDoRequest<'a> {
2644 Ifindex(u32),
2645 Ifname(&'a CStr),
2646 #[doc = "Set to all zeros to remove."]
2647 PrivateKey(&'a [u8]),
2648 PublicKey(&'a [u8]),
2649 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2650 Flags(u32),
2651 #[doc = "Set as 0 to choose randomly."]
2652 ListenPort(u16),
2653 #[doc = "Set as 0 to disable."]
2654 Fwmark(u32),
2655 Peers(IterableArrayWgpeer<'a>),
2656}
2657impl<'a> IterableOpSetDeviceDoRequest<'a> {
2658 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2659 let mut iter = self.clone();
2660 iter.pos = 0;
2661 for attr in iter {
2662 if let OpSetDeviceDoRequest::Ifindex(val) = attr? {
2663 return Ok(val);
2664 }
2665 }
2666 Err(ErrorContext::new_missing(
2667 "OpSetDeviceDoRequest",
2668 "Ifindex",
2669 self.orig_loc,
2670 self.buf.as_ptr() as usize,
2671 ))
2672 }
2673 pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
2674 let mut iter = self.clone();
2675 iter.pos = 0;
2676 for attr in iter {
2677 if let OpSetDeviceDoRequest::Ifname(val) = attr? {
2678 return Ok(val);
2679 }
2680 }
2681 Err(ErrorContext::new_missing(
2682 "OpSetDeviceDoRequest",
2683 "Ifname",
2684 self.orig_loc,
2685 self.buf.as_ptr() as usize,
2686 ))
2687 }
2688 #[doc = "Set to all zeros to remove."]
2689 pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
2690 let mut iter = self.clone();
2691 iter.pos = 0;
2692 for attr in iter {
2693 if let OpSetDeviceDoRequest::PrivateKey(val) = attr? {
2694 return Ok(val);
2695 }
2696 }
2697 Err(ErrorContext::new_missing(
2698 "OpSetDeviceDoRequest",
2699 "PrivateKey",
2700 self.orig_loc,
2701 self.buf.as_ptr() as usize,
2702 ))
2703 }
2704 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
2705 let mut iter = self.clone();
2706 iter.pos = 0;
2707 for attr in iter {
2708 if let OpSetDeviceDoRequest::PublicKey(val) = attr? {
2709 return Ok(val);
2710 }
2711 }
2712 Err(ErrorContext::new_missing(
2713 "OpSetDeviceDoRequest",
2714 "PublicKey",
2715 self.orig_loc,
2716 self.buf.as_ptr() as usize,
2717 ))
2718 }
2719 #[doc = "0 or WGDEVICE_F_REPLACE_PEERS if all current peers\nshould be removed prior to adding the list below.\n\nAssociated type: \"WgdeviceFlags\" (enum)"]
2720 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
2721 let mut iter = self.clone();
2722 iter.pos = 0;
2723 for attr in iter {
2724 if let OpSetDeviceDoRequest::Flags(val) = attr? {
2725 return Ok(val);
2726 }
2727 }
2728 Err(ErrorContext::new_missing(
2729 "OpSetDeviceDoRequest",
2730 "Flags",
2731 self.orig_loc,
2732 self.buf.as_ptr() as usize,
2733 ))
2734 }
2735 #[doc = "Set as 0 to choose randomly."]
2736 pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
2737 let mut iter = self.clone();
2738 iter.pos = 0;
2739 for attr in iter {
2740 if let OpSetDeviceDoRequest::ListenPort(val) = attr? {
2741 return Ok(val);
2742 }
2743 }
2744 Err(ErrorContext::new_missing(
2745 "OpSetDeviceDoRequest",
2746 "ListenPort",
2747 self.orig_loc,
2748 self.buf.as_ptr() as usize,
2749 ))
2750 }
2751 #[doc = "Set as 0 to disable."]
2752 pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
2753 let mut iter = self.clone();
2754 iter.pos = 0;
2755 for attr in iter {
2756 if let OpSetDeviceDoRequest::Fwmark(val) = attr? {
2757 return Ok(val);
2758 }
2759 }
2760 Err(ErrorContext::new_missing(
2761 "OpSetDeviceDoRequest",
2762 "Fwmark",
2763 self.orig_loc,
2764 self.buf.as_ptr() as usize,
2765 ))
2766 }
2767 pub fn get_peers(
2768 &self,
2769 ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
2770 for attr in self.clone() {
2771 if let OpSetDeviceDoRequest::Peers(val) = attr? {
2772 return Ok(ArrayIterable::new(val));
2773 }
2774 }
2775 Err(ErrorContext::new_missing(
2776 "OpSetDeviceDoRequest",
2777 "Peers",
2778 self.orig_loc,
2779 self.buf.as_ptr() as usize,
2780 ))
2781 }
2782}
2783impl<'a> OpSetDeviceDoRequest<'a> {
2784 pub fn new(buf: &'a [u8]) -> IterableOpSetDeviceDoRequest<'a> {
2785 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
2786 IterableOpSetDeviceDoRequest::with_loc(attrs, buf.as_ptr() as usize)
2787 }
2788 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2789 Wgdevice::attr_from_type(r#type)
2790 }
2791}
2792#[derive(Clone, Copy, Default)]
2793pub struct IterableOpSetDeviceDoRequest<'a> {
2794 buf: &'a [u8],
2795 pos: usize,
2796 orig_loc: usize,
2797}
2798impl<'a> IterableOpSetDeviceDoRequest<'a> {
2799 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2800 Self {
2801 buf,
2802 pos: 0,
2803 orig_loc,
2804 }
2805 }
2806 pub fn get_buf(&self) -> &'a [u8] {
2807 self.buf
2808 }
2809}
2810impl<'a> Iterator for IterableOpSetDeviceDoRequest<'a> {
2811 type Item = Result<OpSetDeviceDoRequest<'a>, ErrorContext>;
2812 fn next(&mut self) -> Option<Self::Item> {
2813 if self.buf.len() == self.pos {
2814 return None;
2815 }
2816 let pos = self.pos;
2817 let mut r#type = None;
2818 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2819 r#type = Some(header.r#type);
2820 let res = match header.r#type {
2821 1u16 => OpSetDeviceDoRequest::Ifindex({
2822 let res = parse_u32(next);
2823 let Some(val) = res else { break };
2824 val
2825 }),
2826 2u16 => OpSetDeviceDoRequest::Ifname({
2827 let res = CStr::from_bytes_with_nul(next).ok();
2828 let Some(val) = res else { break };
2829 val
2830 }),
2831 3u16 => OpSetDeviceDoRequest::PrivateKey({
2832 let res = Some(next);
2833 let Some(val) = res else { break };
2834 val
2835 }),
2836 4u16 => OpSetDeviceDoRequest::PublicKey({
2837 let res = Some(next);
2838 let Some(val) = res else { break };
2839 val
2840 }),
2841 5u16 => OpSetDeviceDoRequest::Flags({
2842 let res = parse_u32(next);
2843 let Some(val) = res else { break };
2844 val
2845 }),
2846 6u16 => OpSetDeviceDoRequest::ListenPort({
2847 let res = parse_u16(next);
2848 let Some(val) = res else { break };
2849 val
2850 }),
2851 7u16 => OpSetDeviceDoRequest::Fwmark({
2852 let res = parse_u32(next);
2853 let Some(val) = res else { break };
2854 val
2855 }),
2856 8u16 => OpSetDeviceDoRequest::Peers({
2857 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
2858 let Some(val) = res else { break };
2859 val
2860 }),
2861 n => {
2862 if cfg!(any(test, feature = "deny-unknown-attrs")) {
2863 break;
2864 } else {
2865 continue;
2866 }
2867 }
2868 };
2869 return Some(Ok(res));
2870 }
2871 Some(Err(ErrorContext::new(
2872 "OpSetDeviceDoRequest",
2873 r#type.and_then(|t| OpSetDeviceDoRequest::attr_from_type(t)),
2874 self.orig_loc,
2875 self.buf.as_ptr().wrapping_add(pos) as usize,
2876 )))
2877 }
2878}
2879impl<'a> std::fmt::Debug for IterableOpSetDeviceDoRequest<'_> {
2880 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2881 let mut fmt = f.debug_struct("OpSetDeviceDoRequest");
2882 for attr in self.clone() {
2883 let attr = match attr {
2884 Ok(a) => a,
2885 Err(err) => {
2886 fmt.finish()?;
2887 f.write_str("Err(")?;
2888 err.fmt(f)?;
2889 return f.write_str(")");
2890 }
2891 };
2892 match attr {
2893 OpSetDeviceDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
2894 OpSetDeviceDoRequest::Ifname(val) => fmt.field("Ifname", &val),
2895 OpSetDeviceDoRequest::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
2896 OpSetDeviceDoRequest::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
2897 OpSetDeviceDoRequest::Flags(val) => {
2898 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
2899 }
2900 OpSetDeviceDoRequest::ListenPort(val) => fmt.field("ListenPort", &val),
2901 OpSetDeviceDoRequest::Fwmark(val) => fmt.field("Fwmark", &val),
2902 OpSetDeviceDoRequest::Peers(val) => fmt.field("Peers", &val),
2903 };
2904 }
2905 fmt.finish()
2906 }
2907}
2908impl IterableOpSetDeviceDoRequest<'_> {
2909 pub fn lookup_attr(
2910 &self,
2911 offset: usize,
2912 missing_type: Option<u16>,
2913 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2914 let mut stack = Vec::new();
2915 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2916 if cur == offset + PushBuiltinNfgenmsg::len() {
2917 stack.push(("OpSetDeviceDoRequest", offset));
2918 return (
2919 stack,
2920 missing_type.and_then(|t| OpSetDeviceDoRequest::attr_from_type(t)),
2921 );
2922 }
2923 if cur > offset || cur + self.buf.len() < offset {
2924 return (stack, None);
2925 }
2926 let mut attrs = self.clone();
2927 let mut last_off = cur + attrs.pos;
2928 let mut missing = None;
2929 while let Some(attr) = attrs.next() {
2930 let Ok(attr) = attr else { break };
2931 match attr {
2932 OpSetDeviceDoRequest::Ifindex(val) => {
2933 if last_off == offset {
2934 stack.push(("Ifindex", last_off));
2935 break;
2936 }
2937 }
2938 OpSetDeviceDoRequest::Ifname(val) => {
2939 if last_off == offset {
2940 stack.push(("Ifname", last_off));
2941 break;
2942 }
2943 }
2944 OpSetDeviceDoRequest::PrivateKey(val) => {
2945 if last_off == offset {
2946 stack.push(("PrivateKey", last_off));
2947 break;
2948 }
2949 }
2950 OpSetDeviceDoRequest::PublicKey(val) => {
2951 if last_off == offset {
2952 stack.push(("PublicKey", last_off));
2953 break;
2954 }
2955 }
2956 OpSetDeviceDoRequest::Flags(val) => {
2957 if last_off == offset {
2958 stack.push(("Flags", last_off));
2959 break;
2960 }
2961 }
2962 OpSetDeviceDoRequest::ListenPort(val) => {
2963 if last_off == offset {
2964 stack.push(("ListenPort", last_off));
2965 break;
2966 }
2967 }
2968 OpSetDeviceDoRequest::Fwmark(val) => {
2969 if last_off == offset {
2970 stack.push(("Fwmark", last_off));
2971 break;
2972 }
2973 }
2974 OpSetDeviceDoRequest::Peers(val) => {
2975 for entry in val {
2976 let Ok(attr) = entry else { break };
2977 (stack, missing) = attr.lookup_attr(offset, missing_type);
2978 if !stack.is_empty() {
2979 break;
2980 }
2981 }
2982 if !stack.is_empty() {
2983 stack.push(("Peers", last_off));
2984 break;
2985 }
2986 }
2987 _ => {}
2988 };
2989 last_off = cur + attrs.pos;
2990 }
2991 if !stack.is_empty() {
2992 stack.push(("OpSetDeviceDoRequest", cur));
2993 }
2994 (stack, missing)
2995 }
2996}
2997#[doc = "Set WireGuard device.\n\nThis command should be called with a wgdevice set, containing one but\nnot both of WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME.\n\nIt is possible that the amount of configuration data exceeds that of\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended after.\nLikewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments.\n\nIf an error occurs, NLMSG_ERROR will reply containing an errno.\n"]
2998pub struct PushOpSetDeviceDoReply<Prev: Rec> {
2999 pub(crate) prev: Option<Prev>,
3000 pub(crate) header_offset: Option<usize>,
3001}
3002impl<Prev: Rec> Rec for PushOpSetDeviceDoReply<Prev> {
3003 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3004 self.prev.as_mut().unwrap().as_rec_mut()
3005 }
3006}
3007impl<Prev: Rec> PushOpSetDeviceDoReply<Prev> {
3008 pub fn new(mut prev: Prev) -> Self {
3009 Self::write_header(&mut prev);
3010 Self::new_without_header(prev)
3011 }
3012 fn new_without_header(prev: Prev) -> Self {
3013 Self {
3014 prev: Some(prev),
3015 header_offset: None,
3016 }
3017 }
3018 fn write_header(prev: &mut Prev) {
3019 let mut header = PushBuiltinNfgenmsg::new();
3020 header.set_cmd(1u8);
3021 header.set_version(1u8);
3022 prev.as_rec_mut().extend(header.as_slice());
3023 }
3024 pub fn end_nested(mut self) -> Prev {
3025 let mut prev = self.prev.take().unwrap();
3026 if let Some(header_offset) = &self.header_offset {
3027 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3028 }
3029 prev
3030 }
3031}
3032impl<Prev: Rec> Drop for PushOpSetDeviceDoReply<Prev> {
3033 fn drop(&mut self) {
3034 if let Some(prev) = &mut self.prev {
3035 if let Some(header_offset) = &self.header_offset {
3036 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3037 }
3038 }
3039 }
3040}
3041#[doc = "Set WireGuard device.\n\nThis command should be called with a wgdevice set, containing one but\nnot both of WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME.\n\nIt is possible that the amount of configuration data exceeds that of\nthe maximum message length accepted by the kernel. In that case,\nseveral messages should be sent one after another, with each\nsuccessive one filling in information not contained in the prior.\nNote that if WGDEVICE_F_REPLACE_PEERS is specified in the first\nmessage, it probably should not be specified in fragments that come\nafter, so that the list of peers is only cleared the first time but\nappended after.\nLikewise for peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in\nthe first message of a peer, it likely should not be specified in\nsubsequent fragments.\n\nIf an error occurs, NLMSG_ERROR will reply containing an errno.\n"]
3042#[derive(Clone)]
3043pub enum OpSetDeviceDoReply {}
3044impl<'a> IterableOpSetDeviceDoReply<'a> {}
3045impl OpSetDeviceDoReply {
3046 pub fn new(buf: &'_ [u8]) -> IterableOpSetDeviceDoReply<'_> {
3047 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
3048 IterableOpSetDeviceDoReply::with_loc(attrs, buf.as_ptr() as usize)
3049 }
3050 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3051 Wgdevice::attr_from_type(r#type)
3052 }
3053}
3054#[derive(Clone, Copy, Default)]
3055pub struct IterableOpSetDeviceDoReply<'a> {
3056 buf: &'a [u8],
3057 pos: usize,
3058 orig_loc: usize,
3059}
3060impl<'a> IterableOpSetDeviceDoReply<'a> {
3061 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3062 Self {
3063 buf,
3064 pos: 0,
3065 orig_loc,
3066 }
3067 }
3068 pub fn get_buf(&self) -> &'a [u8] {
3069 self.buf
3070 }
3071}
3072impl<'a> Iterator for IterableOpSetDeviceDoReply<'a> {
3073 type Item = Result<OpSetDeviceDoReply, ErrorContext>;
3074 fn next(&mut self) -> Option<Self::Item> {
3075 if self.buf.len() == self.pos {
3076 return None;
3077 }
3078 let pos = self.pos;
3079 let mut r#type = None;
3080 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3081 r#type = Some(header.r#type);
3082 let res = match header.r#type {
3083 n => {
3084 if cfg!(any(test, feature = "deny-unknown-attrs")) {
3085 break;
3086 } else {
3087 continue;
3088 }
3089 }
3090 };
3091 return Some(Ok(res));
3092 }
3093 Some(Err(ErrorContext::new(
3094 "OpSetDeviceDoReply",
3095 r#type.and_then(|t| OpSetDeviceDoReply::attr_from_type(t)),
3096 self.orig_loc,
3097 self.buf.as_ptr().wrapping_add(pos) as usize,
3098 )))
3099 }
3100}
3101impl std::fmt::Debug for IterableOpSetDeviceDoReply<'_> {
3102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3103 let mut fmt = f.debug_struct("OpSetDeviceDoReply");
3104 for attr in self.clone() {
3105 let attr = match attr {
3106 Ok(a) => a,
3107 Err(err) => {
3108 fmt.finish()?;
3109 f.write_str("Err(")?;
3110 err.fmt(f)?;
3111 return f.write_str(")");
3112 }
3113 };
3114 match attr {};
3115 }
3116 fmt.finish()
3117 }
3118}
3119impl IterableOpSetDeviceDoReply<'_> {
3120 pub fn lookup_attr(
3121 &self,
3122 offset: usize,
3123 missing_type: Option<u16>,
3124 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3125 let mut stack = Vec::new();
3126 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3127 if cur == offset + PushBuiltinNfgenmsg::len() {
3128 stack.push(("OpSetDeviceDoReply", offset));
3129 return (
3130 stack,
3131 missing_type.and_then(|t| OpSetDeviceDoReply::attr_from_type(t)),
3132 );
3133 }
3134 (stack, None)
3135 }
3136}
3137#[derive(Debug)]
3138pub struct RequestOpSetDeviceDoRequest<'r> {
3139 request: Request<'r>,
3140}
3141impl<'r> RequestOpSetDeviceDoRequest<'r> {
3142 pub fn new(mut request: Request<'r>) -> Self {
3143 PushOpSetDeviceDoRequest::write_header(&mut request.buf_mut());
3144 Self { request: request }
3145 }
3146 pub fn encode(&mut self) -> PushOpSetDeviceDoRequest<&mut Vec<u8>> {
3147 PushOpSetDeviceDoRequest::new_without_header(self.request.buf_mut())
3148 }
3149 pub fn into_encoder(self) -> PushOpSetDeviceDoRequest<RequestBuf<'r>> {
3150 PushOpSetDeviceDoRequest::new_without_header(self.request.buf)
3151 }
3152}
3153impl NetlinkRequest for RequestOpSetDeviceDoRequest<'_> {
3154 type ReplyType<'buf> = IterableOpSetDeviceDoReply<'buf>;
3155 fn protocol(&self) -> Protocol {
3156 Protocol::Generic("wireguard".as_bytes())
3157 }
3158 fn flags(&self) -> u16 {
3159 self.request.flags
3160 }
3161 fn payload(&self) -> &[u8] {
3162 self.request.buf()
3163 }
3164 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
3165 OpSetDeviceDoReply::new(buf)
3166 }
3167 fn lookup(
3168 buf: &[u8],
3169 offset: usize,
3170 missing_type: Option<u16>,
3171 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3172 OpSetDeviceDoRequest::new(buf).lookup_attr(offset, missing_type)
3173 }
3174}
3175use crate::traits::LookupFn;
3176use crate::utils::RequestBuf;
3177#[derive(Debug)]
3178pub struct Request<'buf> {
3179 buf: RequestBuf<'buf>,
3180 flags: u16,
3181 writeback: Option<&'buf mut Option<RequestInfo>>,
3182}
3183#[allow(unused)]
3184#[derive(Debug, Clone)]
3185pub struct RequestInfo {
3186 protocol: Protocol,
3187 flags: u16,
3188 name: &'static str,
3189 lookup: LookupFn,
3190}
3191impl Request<'static> {
3192 pub fn new() -> Self {
3193 Self::new_from_buf(Vec::new())
3194 }
3195 pub fn new_from_buf(buf: Vec<u8>) -> Self {
3196 Self {
3197 flags: 0,
3198 buf: RequestBuf::Own(buf),
3199 writeback: None,
3200 }
3201 }
3202 pub fn into_buf(self) -> Vec<u8> {
3203 match self.buf {
3204 RequestBuf::Own(buf) => buf,
3205 _ => unreachable!(),
3206 }
3207 }
3208}
3209impl<'buf> Request<'buf> {
3210 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
3211 buf.clear();
3212 Self::new_extend(buf)
3213 }
3214 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
3215 Self {
3216 flags: 0,
3217 buf: RequestBuf::Ref(buf),
3218 writeback: None,
3219 }
3220 }
3221 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
3222 let Some(writeback) = &mut self.writeback else {
3223 return;
3224 };
3225 **writeback = Some(RequestInfo {
3226 protocol,
3227 flags: self.flags,
3228 name,
3229 lookup,
3230 })
3231 }
3232 pub fn buf(&self) -> &Vec<u8> {
3233 self.buf.buf()
3234 }
3235 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
3236 self.buf.buf_mut()
3237 }
3238 #[doc = "Set `NLM_F_CREATE` flag"]
3239 pub fn set_create(mut self) -> Self {
3240 self.flags |= consts::NLM_F_CREATE as u16;
3241 self
3242 }
3243 #[doc = "Set `NLM_F_EXCL` flag"]
3244 pub fn set_excl(mut self) -> Self {
3245 self.flags |= consts::NLM_F_EXCL as u16;
3246 self
3247 }
3248 #[doc = "Set `NLM_F_REPLACE` flag"]
3249 pub fn set_replace(mut self) -> Self {
3250 self.flags |= consts::NLM_F_REPLACE as u16;
3251 self
3252 }
3253 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
3254 pub fn set_change(self) -> Self {
3255 self.set_create().set_replace()
3256 }
3257 #[doc = "Set `NLM_F_APPEND` flag"]
3258 pub fn set_append(mut self) -> Self {
3259 self.flags |= consts::NLM_F_APPEND as u16;
3260 self
3261 }
3262 #[doc = "Set `NLM_F_DUMP` flag"]
3263 fn set_dump(mut self) -> Self {
3264 self.flags |= consts::NLM_F_DUMP as u16;
3265 self
3266 }
3267 pub fn op_get_device_dump_request(self) -> RequestOpGetDeviceDumpRequest<'buf> {
3268 let mut res = RequestOpGetDeviceDumpRequest::new(self);
3269 res.request.do_writeback(
3270 res.protocol(),
3271 "op-get-device-dump-request",
3272 RequestOpGetDeviceDumpRequest::lookup,
3273 );
3274 res
3275 }
3276 pub fn op_set_device_do_request(self) -> RequestOpSetDeviceDoRequest<'buf> {
3277 let mut res = RequestOpSetDeviceDoRequest::new(self);
3278 res.request.do_writeback(
3279 res.protocol(),
3280 "op-set-device-do-request",
3281 RequestOpSetDeviceDoRequest::lookup,
3282 );
3283 res
3284 }
3285}