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