1#![doc = "**Netlink protocol to control WireGuard network devices.**\n\nThe below enums and macros are for interfacing with WireGuard, using\ngeneric netlink, with family `WG_GENL_NAME` and version\n`WG_GENL_VERSION`. It defines two commands: get and set. Note that while\nthey share many common attributes, these two commands actually accept a\nslightly different set of inputs and outputs. These differences are\nnoted 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::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
13use crate::{
14 consts,
15 traits::{NetlinkRequest, Protocol},
16 utils::*,
17};
18pub const PROTONAME: &str = "wireguard";
19pub const PROTONAME_CSTR: &CStr = c"wireguard";
20pub const KEY_LEN: u64 = 32u64;
21#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
22#[derive(Debug, Clone, Copy)]
23pub enum WgdeviceFlags {
24 ReplacePeers = 1 << 0,
25}
26impl WgdeviceFlags {
27 pub fn from_value(value: u64) -> Option<Self> {
28 Some(match value {
29 n if n == 1 << 0 => Self::ReplacePeers,
30 _ => return None,
31 })
32 }
33}
34#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
35#[derive(Debug, Clone, Copy)]
36pub enum WgpeerFlags {
37 RemoveMe = 1 << 0,
38 ReplaceAllowedips = 1 << 1,
39 UpdateOnly = 1 << 2,
40}
41impl WgpeerFlags {
42 pub fn from_value(value: u64) -> Option<Self> {
43 Some(match value {
44 n if n == 1 << 0 => Self::RemoveMe,
45 n if n == 1 << 1 => Self::ReplaceAllowedips,
46 n if n == 1 << 2 => Self::UpdateOnly,
47 _ => return None,
48 })
49 }
50}
51#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
52#[derive(Debug, Clone, Copy)]
53pub enum WgallowedipFlags {
54 RemoveMe = 1 << 0,
55}
56impl WgallowedipFlags {
57 pub fn from_value(value: u64) -> Option<Self> {
58 Some(match value {
59 n if n == 1 << 0 => Self::RemoveMe,
60 _ => return None,
61 })
62 }
63}
64#[repr(C, packed(4))]
65pub struct KernelTimespec {
66 #[doc = "Number of seconds, since UNIX epoch.\n"]
67 pub sec: u64,
68 #[doc = "Number of nanoseconds, after the second began.\n"]
69 pub nsec: u64,
70}
71impl Clone for KernelTimespec {
72 fn clone(&self) -> Self {
73 Self::new_from_array(*self.as_array())
74 }
75}
76#[doc = "Create zero-initialized struct"]
77impl Default for KernelTimespec {
78 fn default() -> Self {
79 Self::new()
80 }
81}
82impl KernelTimespec {
83 #[doc = "Create zero-initialized struct"]
84 pub fn new() -> Self {
85 Self::new_from_array([0u8; Self::len()])
86 }
87 #[doc = "Copy from contents from slice"]
88 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
89 if other.len() != Self::len() {
90 return None;
91 }
92 let mut buf = [0u8; Self::len()];
93 buf.clone_from_slice(other);
94 Some(Self::new_from_array(buf))
95 }
96 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
97 pub fn new_from_zeroed(other: &[u8]) -> Self {
98 let mut buf = [0u8; Self::len()];
99 let len = buf.len().min(other.len());
100 buf[..len].clone_from_slice(&other[..len]);
101 Self::new_from_array(buf)
102 }
103 pub fn new_from_array(buf: [u8; 16usize]) -> Self {
104 unsafe { std::mem::transmute(buf) }
105 }
106 pub fn as_slice(&self) -> &[u8] {
107 unsafe {
108 let ptr: *const u8 = std::mem::transmute(self as *const Self);
109 std::slice::from_raw_parts(ptr, Self::len())
110 }
111 }
112 pub fn from_slice(buf: &[u8]) -> &Self {
113 assert!(buf.len() >= Self::len());
114 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
115 unsafe { std::mem::transmute(buf.as_ptr()) }
116 }
117 pub fn as_array(&self) -> &[u8; 16usize] {
118 unsafe { std::mem::transmute(self) }
119 }
120 pub fn from_array(buf: &[u8; 16usize]) -> &Self {
121 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
122 unsafe { std::mem::transmute(buf) }
123 }
124 pub fn into_array(self) -> [u8; 16usize] {
125 unsafe { std::mem::transmute(self) }
126 }
127 pub const fn len() -> usize {
128 const _: () = assert!(std::mem::size_of::<KernelTimespec>() == 16usize);
129 16usize
130 }
131}
132impl std::fmt::Debug for KernelTimespec {
133 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 fmt.debug_struct("KernelTimespec")
135 .field("sec", &{ self.sec })
136 .field("nsec", &{ self.nsec })
137 .finish()
138 }
139}
140#[derive(Clone)]
141pub enum Wgdevice<'a> {
142 Ifindex(u32),
143 Ifname(&'a CStr),
144 #[doc = "Set to all zeros to remove.\n"]
145 PrivateKey(&'a [u8]),
146 PublicKey(&'a [u8]),
147 #[doc = "`0` or `WGDEVICE_F_REPLACE_PEERS` if all current peers should be removed\nprior to adding the list below.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
148 Flags(u32),
149 #[doc = "Set as `0` to choose randomly.\n"]
150 ListenPort(u16),
151 #[doc = "Set as `0` to disable.\n"]
152 Fwmark(u32),
153 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
154 Peers(IterableArrayWgpeer<'a>),
155}
156impl<'a> IterableWgdevice<'a> {
157 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
158 let mut iter = self.clone();
159 iter.pos = 0;
160 for attr in iter {
161 if let Ok(Wgdevice::Ifindex(val)) = attr {
162 return Ok(val);
163 }
164 }
165 Err(ErrorContext::new_missing(
166 "Wgdevice",
167 "Ifindex",
168 self.orig_loc,
169 self.buf.as_ptr() as usize,
170 ))
171 }
172 pub fn get_ifname(&self) -> Result<&'a CStr, ErrorContext> {
173 let mut iter = self.clone();
174 iter.pos = 0;
175 for attr in iter {
176 if let Ok(Wgdevice::Ifname(val)) = attr {
177 return Ok(val);
178 }
179 }
180 Err(ErrorContext::new_missing(
181 "Wgdevice",
182 "Ifname",
183 self.orig_loc,
184 self.buf.as_ptr() as usize,
185 ))
186 }
187 #[doc = "Set to all zeros to remove.\n"]
188 pub fn get_private_key(&self) -> Result<&'a [u8], ErrorContext> {
189 let mut iter = self.clone();
190 iter.pos = 0;
191 for attr in iter {
192 if let Ok(Wgdevice::PrivateKey(val)) = attr {
193 return Ok(val);
194 }
195 }
196 Err(ErrorContext::new_missing(
197 "Wgdevice",
198 "PrivateKey",
199 self.orig_loc,
200 self.buf.as_ptr() as usize,
201 ))
202 }
203 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
204 let mut iter = self.clone();
205 iter.pos = 0;
206 for attr in iter {
207 if let Ok(Wgdevice::PublicKey(val)) = attr {
208 return Ok(val);
209 }
210 }
211 Err(ErrorContext::new_missing(
212 "Wgdevice",
213 "PublicKey",
214 self.orig_loc,
215 self.buf.as_ptr() as usize,
216 ))
217 }
218 #[doc = "`0` or `WGDEVICE_F_REPLACE_PEERS` if all current peers should be removed\nprior to adding the list below.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
219 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
220 let mut iter = self.clone();
221 iter.pos = 0;
222 for attr in iter {
223 if let Ok(Wgdevice::Flags(val)) = attr {
224 return Ok(val);
225 }
226 }
227 Err(ErrorContext::new_missing(
228 "Wgdevice",
229 "Flags",
230 self.orig_loc,
231 self.buf.as_ptr() as usize,
232 ))
233 }
234 #[doc = "Set as `0` to choose randomly.\n"]
235 pub fn get_listen_port(&self) -> Result<u16, ErrorContext> {
236 let mut iter = self.clone();
237 iter.pos = 0;
238 for attr in iter {
239 if let Ok(Wgdevice::ListenPort(val)) = attr {
240 return Ok(val);
241 }
242 }
243 Err(ErrorContext::new_missing(
244 "Wgdevice",
245 "ListenPort",
246 self.orig_loc,
247 self.buf.as_ptr() as usize,
248 ))
249 }
250 #[doc = "Set as `0` to disable.\n"]
251 pub fn get_fwmark(&self) -> Result<u32, ErrorContext> {
252 let mut iter = self.clone();
253 iter.pos = 0;
254 for attr in iter {
255 if let Ok(Wgdevice::Fwmark(val)) = attr {
256 return Ok(val);
257 }
258 }
259 Err(ErrorContext::new_missing(
260 "Wgdevice",
261 "Fwmark",
262 self.orig_loc,
263 self.buf.as_ptr() as usize,
264 ))
265 }
266 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
267 pub fn get_peers(
268 &self,
269 ) -> Result<ArrayIterable<IterableArrayWgpeer<'a>, IterableWgpeer<'a>>, ErrorContext> {
270 for attr in self.clone() {
271 if let Ok(Wgdevice::Peers(val)) = attr {
272 return Ok(ArrayIterable::new(val));
273 }
274 }
275 Err(ErrorContext::new_missing(
276 "Wgdevice",
277 "Peers",
278 self.orig_loc,
279 self.buf.as_ptr() as usize,
280 ))
281 }
282}
283impl<'a> Wgpeer<'a> {
284 pub fn new_array(buf: &[u8]) -> IterableArrayWgpeer<'_> {
285 IterableArrayWgpeer::with_loc(buf, buf.as_ptr() as usize)
286 }
287}
288#[derive(Clone, Copy, Default)]
289pub struct IterableArrayWgpeer<'a> {
290 buf: &'a [u8],
291 pos: usize,
292 orig_loc: usize,
293}
294impl<'a> IterableArrayWgpeer<'a> {
295 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
296 Self {
297 buf,
298 pos: 0,
299 orig_loc,
300 }
301 }
302 pub fn get_buf(&self) -> &'a [u8] {
303 self.buf
304 }
305}
306impl<'a> Iterator for IterableArrayWgpeer<'a> {
307 type Item = Result<IterableWgpeer<'a>, ErrorContext>;
308 fn next(&mut self) -> Option<Self::Item> {
309 if self.buf.len() == self.pos {
310 return None;
311 }
312 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
313 {
314 return Some(Ok(IterableWgpeer::with_loc(next, self.orig_loc)));
315 }
316 }
317 let pos = self.pos;
318 self.pos = self.buf.len();
319 Some(Err(ErrorContext::new(
320 "Wgpeer",
321 None,
322 self.orig_loc,
323 self.buf.as_ptr().wrapping_add(pos) as usize,
324 )))
325 }
326}
327impl Wgdevice<'_> {
328 pub fn new<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
329 IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
330 }
331 fn attr_from_type(r#type: u16) -> Option<&'static str> {
332 let res = match r#type {
333 0u16 => "Unspec",
334 1u16 => "Ifindex",
335 2u16 => "Ifname",
336 3u16 => "PrivateKey",
337 4u16 => "PublicKey",
338 5u16 => "Flags",
339 6u16 => "ListenPort",
340 7u16 => "Fwmark",
341 8u16 => "Peers",
342 _ => return None,
343 };
344 Some(res)
345 }
346}
347#[derive(Clone, Copy, Default)]
348pub struct IterableWgdevice<'a> {
349 buf: &'a [u8],
350 pos: usize,
351 orig_loc: usize,
352}
353impl<'a> IterableWgdevice<'a> {
354 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
355 Self {
356 buf,
357 pos: 0,
358 orig_loc,
359 }
360 }
361 pub fn get_buf(&self) -> &'a [u8] {
362 self.buf
363 }
364}
365impl<'a> Iterator for IterableWgdevice<'a> {
366 type Item = Result<Wgdevice<'a>, ErrorContext>;
367 fn next(&mut self) -> Option<Self::Item> {
368 let mut pos;
369 let mut r#type;
370 loop {
371 pos = self.pos;
372 r#type = None;
373 if self.buf.len() == self.pos {
374 return None;
375 }
376 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
377 self.pos = self.buf.len();
378 break;
379 };
380 r#type = Some(header.r#type);
381 let res = match header.r#type {
382 1u16 => Wgdevice::Ifindex({
383 let res = parse_u32(next);
384 let Some(val) = res else { break };
385 val
386 }),
387 2u16 => Wgdevice::Ifname({
388 let res = CStr::from_bytes_with_nul(next).ok();
389 let Some(val) = res else { break };
390 val
391 }),
392 3u16 => Wgdevice::PrivateKey({
393 let res = Some(next);
394 let Some(val) = res else { break };
395 val
396 }),
397 4u16 => Wgdevice::PublicKey({
398 let res = Some(next);
399 let Some(val) = res else { break };
400 val
401 }),
402 5u16 => Wgdevice::Flags({
403 let res = parse_u32(next);
404 let Some(val) = res else { break };
405 val
406 }),
407 6u16 => Wgdevice::ListenPort({
408 let res = parse_u16(next);
409 let Some(val) = res else { break };
410 val
411 }),
412 7u16 => Wgdevice::Fwmark({
413 let res = parse_u32(next);
414 let Some(val) = res else { break };
415 val
416 }),
417 8u16 => Wgdevice::Peers({
418 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
419 let Some(val) = res else { break };
420 val
421 }),
422 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
423 n => continue,
424 };
425 return Some(Ok(res));
426 }
427 Some(Err(ErrorContext::new(
428 "Wgdevice",
429 r#type.and_then(|t| Wgdevice::attr_from_type(t)),
430 self.orig_loc,
431 self.buf.as_ptr().wrapping_add(pos) as usize,
432 )))
433 }
434}
435impl std::fmt::Debug for IterableArrayWgpeer<'_> {
436 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 fmt.debug_list()
438 .entries(self.clone().map(FlattenErrorContext))
439 .finish()
440 }
441}
442impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
443 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
444 let mut fmt = f.debug_struct("Wgdevice");
445 for attr in self.clone() {
446 let attr = match attr {
447 Ok(a) => a,
448 Err(err) => {
449 fmt.finish()?;
450 f.write_str("Err(")?;
451 err.fmt(f)?;
452 return f.write_str(")");
453 }
454 };
455 match attr {
456 Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
457 Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
458 Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
459 Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
460 Wgdevice::Flags(val) => {
461 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
462 }
463 Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
464 Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
465 Wgdevice::Peers(val) => fmt.field("Peers", &val),
466 };
467 }
468 fmt.finish()
469 }
470}
471impl IterableWgdevice<'_> {
472 pub fn lookup_attr(
473 &self,
474 offset: usize,
475 missing_type: Option<u16>,
476 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
477 let mut stack = Vec::new();
478 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
479 if missing_type.is_some() && cur == offset {
480 stack.push(("Wgdevice", offset));
481 return (
482 stack,
483 missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
484 );
485 }
486 if cur > offset || cur + self.buf.len() < offset {
487 return (stack, None);
488 }
489 let mut attrs = self.clone();
490 let mut last_off = cur + attrs.pos;
491 let mut missing = None;
492 while let Some(attr) = attrs.next() {
493 let Ok(attr) = attr else { break };
494 match attr {
495 Wgdevice::Ifindex(val) => {
496 if last_off == offset {
497 stack.push(("Ifindex", last_off));
498 break;
499 }
500 }
501 Wgdevice::Ifname(val) => {
502 if last_off == offset {
503 stack.push(("Ifname", last_off));
504 break;
505 }
506 }
507 Wgdevice::PrivateKey(val) => {
508 if last_off == offset {
509 stack.push(("PrivateKey", last_off));
510 break;
511 }
512 }
513 Wgdevice::PublicKey(val) => {
514 if last_off == offset {
515 stack.push(("PublicKey", last_off));
516 break;
517 }
518 }
519 Wgdevice::Flags(val) => {
520 if last_off == offset {
521 stack.push(("Flags", last_off));
522 break;
523 }
524 }
525 Wgdevice::ListenPort(val) => {
526 if last_off == offset {
527 stack.push(("ListenPort", last_off));
528 break;
529 }
530 }
531 Wgdevice::Fwmark(val) => {
532 if last_off == offset {
533 stack.push(("Fwmark", last_off));
534 break;
535 }
536 }
537 Wgdevice::Peers(val) => {
538 for entry in val {
539 let Ok(attr) = entry else { break };
540 (stack, missing) = attr.lookup_attr(offset, missing_type);
541 if !stack.is_empty() {
542 break;
543 }
544 }
545 if !stack.is_empty() {
546 stack.push(("Peers", last_off));
547 break;
548 }
549 }
550 _ => {}
551 };
552 last_off = cur + attrs.pos;
553 }
554 if !stack.is_empty() {
555 stack.push(("Wgdevice", cur));
556 }
557 (stack, missing)
558 }
559}
560#[derive(Clone)]
561pub enum Wgpeer<'a> {
562 PublicKey(&'a [u8]),
563 #[doc = "Set as all zeros to remove.\n"]
564 PresharedKey(&'a [u8]),
565 #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould be removed prior to adding the list below and/or\n`WGPEER_F_UPDATE_ONLY` if the peer should only be set if it already\nexists.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
566 Flags(u32),
567 #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
568 Endpoint(std::net::SocketAddr),
569 #[doc = "Set as `0` to disable.\n"]
570 PersistentKeepaliveInterval(u16),
571 LastHandshakeTime(KernelTimespec),
572 RxBytes(u64),
573 TxBytes(u64),
574 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
575 Allowedips(IterableArrayWgallowedip<'a>),
576 #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
577 ProtocolVersion(u32),
578}
579impl<'a> IterableWgpeer<'a> {
580 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
581 let mut iter = self.clone();
582 iter.pos = 0;
583 for attr in iter {
584 if let Ok(Wgpeer::PublicKey(val)) = attr {
585 return Ok(val);
586 }
587 }
588 Err(ErrorContext::new_missing(
589 "Wgpeer",
590 "PublicKey",
591 self.orig_loc,
592 self.buf.as_ptr() as usize,
593 ))
594 }
595 #[doc = "Set as all zeros to remove.\n"]
596 pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
597 let mut iter = self.clone();
598 iter.pos = 0;
599 for attr in iter {
600 if let Ok(Wgpeer::PresharedKey(val)) = attr {
601 return Ok(val);
602 }
603 }
604 Err(ErrorContext::new_missing(
605 "Wgpeer",
606 "PresharedKey",
607 self.orig_loc,
608 self.buf.as_ptr() as usize,
609 ))
610 }
611 #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould be removed prior to adding the list below and/or\n`WGPEER_F_UPDATE_ONLY` if the peer should only be set if it already\nexists.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
612 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
613 let mut iter = self.clone();
614 iter.pos = 0;
615 for attr in iter {
616 if let Ok(Wgpeer::Flags(val)) = attr {
617 return Ok(val);
618 }
619 }
620 Err(ErrorContext::new_missing(
621 "Wgpeer",
622 "Flags",
623 self.orig_loc,
624 self.buf.as_ptr() as usize,
625 ))
626 }
627 #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
628 pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
629 let mut iter = self.clone();
630 iter.pos = 0;
631 for attr in iter {
632 if let Ok(Wgpeer::Endpoint(val)) = attr {
633 return Ok(val);
634 }
635 }
636 Err(ErrorContext::new_missing(
637 "Wgpeer",
638 "Endpoint",
639 self.orig_loc,
640 self.buf.as_ptr() as usize,
641 ))
642 }
643 #[doc = "Set as `0` to disable.\n"]
644 pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
645 let mut iter = self.clone();
646 iter.pos = 0;
647 for attr in iter {
648 if let Ok(Wgpeer::PersistentKeepaliveInterval(val)) = attr {
649 return Ok(val);
650 }
651 }
652 Err(ErrorContext::new_missing(
653 "Wgpeer",
654 "PersistentKeepaliveInterval",
655 self.orig_loc,
656 self.buf.as_ptr() as usize,
657 ))
658 }
659 pub fn get_last_handshake_time(&self) -> Result<KernelTimespec, ErrorContext> {
660 let mut iter = self.clone();
661 iter.pos = 0;
662 for attr in iter {
663 if let Ok(Wgpeer::LastHandshakeTime(val)) = attr {
664 return Ok(val);
665 }
666 }
667 Err(ErrorContext::new_missing(
668 "Wgpeer",
669 "LastHandshakeTime",
670 self.orig_loc,
671 self.buf.as_ptr() as usize,
672 ))
673 }
674 pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
675 let mut iter = self.clone();
676 iter.pos = 0;
677 for attr in iter {
678 if let Ok(Wgpeer::RxBytes(val)) = attr {
679 return Ok(val);
680 }
681 }
682 Err(ErrorContext::new_missing(
683 "Wgpeer",
684 "RxBytes",
685 self.orig_loc,
686 self.buf.as_ptr() as usize,
687 ))
688 }
689 pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
690 let mut iter = self.clone();
691 iter.pos = 0;
692 for attr in iter {
693 if let Ok(Wgpeer::TxBytes(val)) = attr {
694 return Ok(val);
695 }
696 }
697 Err(ErrorContext::new_missing(
698 "Wgpeer",
699 "TxBytes",
700 self.orig_loc,
701 self.buf.as_ptr() as usize,
702 ))
703 }
704 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
705 pub fn get_allowedips(
706 &self,
707 ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
708 {
709 for attr in self.clone() {
710 if let Ok(Wgpeer::Allowedips(val)) = attr {
711 return Ok(ArrayIterable::new(val));
712 }
713 }
714 Err(ErrorContext::new_missing(
715 "Wgpeer",
716 "Allowedips",
717 self.orig_loc,
718 self.buf.as_ptr() as usize,
719 ))
720 }
721 #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
722 pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
723 let mut iter = self.clone();
724 iter.pos = 0;
725 for attr in iter {
726 if let Ok(Wgpeer::ProtocolVersion(val)) = attr {
727 return Ok(val);
728 }
729 }
730 Err(ErrorContext::new_missing(
731 "Wgpeer",
732 "ProtocolVersion",
733 self.orig_loc,
734 self.buf.as_ptr() as usize,
735 ))
736 }
737}
738impl Wgallowedip {
739 pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
740 IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
741 }
742}
743#[derive(Clone, Copy, Default)]
744pub struct IterableArrayWgallowedip<'a> {
745 buf: &'a [u8],
746 pos: usize,
747 orig_loc: usize,
748}
749impl<'a> IterableArrayWgallowedip<'a> {
750 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
751 Self {
752 buf,
753 pos: 0,
754 orig_loc,
755 }
756 }
757 pub fn get_buf(&self) -> &'a [u8] {
758 self.buf
759 }
760}
761impl<'a> Iterator for IterableArrayWgallowedip<'a> {
762 type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
763 fn next(&mut self) -> Option<Self::Item> {
764 if self.buf.len() == self.pos {
765 return None;
766 }
767 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
768 {
769 return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
770 }
771 }
772 let pos = self.pos;
773 self.pos = self.buf.len();
774 Some(Err(ErrorContext::new(
775 "Wgallowedip",
776 None,
777 self.orig_loc,
778 self.buf.as_ptr().wrapping_add(pos) as usize,
779 )))
780 }
781}
782impl Wgpeer<'_> {
783 pub fn new<'a>(buf: &'a [u8]) -> IterableWgpeer<'a> {
784 IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
785 }
786 fn attr_from_type(r#type: u16) -> Option<&'static str> {
787 let res = match r#type {
788 0u16 => "Unspec",
789 1u16 => "PublicKey",
790 2u16 => "PresharedKey",
791 3u16 => "Flags",
792 4u16 => "Endpoint",
793 5u16 => "PersistentKeepaliveInterval",
794 6u16 => "LastHandshakeTime",
795 7u16 => "RxBytes",
796 8u16 => "TxBytes",
797 9u16 => "Allowedips",
798 10u16 => "ProtocolVersion",
799 _ => return None,
800 };
801 Some(res)
802 }
803}
804#[derive(Clone, Copy, Default)]
805pub struct IterableWgpeer<'a> {
806 buf: &'a [u8],
807 pos: usize,
808 orig_loc: usize,
809}
810impl<'a> IterableWgpeer<'a> {
811 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
812 Self {
813 buf,
814 pos: 0,
815 orig_loc,
816 }
817 }
818 pub fn get_buf(&self) -> &'a [u8] {
819 self.buf
820 }
821}
822impl<'a> Iterator for IterableWgpeer<'a> {
823 type Item = Result<Wgpeer<'a>, ErrorContext>;
824 fn next(&mut self) -> Option<Self::Item> {
825 let mut pos;
826 let mut r#type;
827 loop {
828 pos = self.pos;
829 r#type = None;
830 if self.buf.len() == self.pos {
831 return None;
832 }
833 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
834 self.pos = self.buf.len();
835 break;
836 };
837 r#type = Some(header.r#type);
838 let res = match header.r#type {
839 1u16 => Wgpeer::PublicKey({
840 let res = Some(next);
841 let Some(val) = res else { break };
842 val
843 }),
844 2u16 => Wgpeer::PresharedKey({
845 let res = Some(next);
846 let Some(val) = res else { break };
847 val
848 }),
849 3u16 => Wgpeer::Flags({
850 let res = parse_u32(next);
851 let Some(val) = res else { break };
852 val
853 }),
854 4u16 => Wgpeer::Endpoint({
855 let res = parse_sockaddr(next);
856 let Some(val) = res else { break };
857 val
858 }),
859 5u16 => Wgpeer::PersistentKeepaliveInterval({
860 let res = parse_u16(next);
861 let Some(val) = res else { break };
862 val
863 }),
864 6u16 => Wgpeer::LastHandshakeTime({
865 let res = Some(KernelTimespec::new_from_zeroed(next));
866 let Some(val) = res else { break };
867 val
868 }),
869 7u16 => Wgpeer::RxBytes({
870 let res = parse_u64(next);
871 let Some(val) = res else { break };
872 val
873 }),
874 8u16 => Wgpeer::TxBytes({
875 let res = parse_u64(next);
876 let Some(val) = res else { break };
877 val
878 }),
879 9u16 => Wgpeer::Allowedips({
880 let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
881 let Some(val) = res else { break };
882 val
883 }),
884 10u16 => Wgpeer::ProtocolVersion({
885 let res = parse_u32(next);
886 let Some(val) = res else { break };
887 val
888 }),
889 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
890 n => continue,
891 };
892 return Some(Ok(res));
893 }
894 Some(Err(ErrorContext::new(
895 "Wgpeer",
896 r#type.and_then(|t| Wgpeer::attr_from_type(t)),
897 self.orig_loc,
898 self.buf.as_ptr().wrapping_add(pos) as usize,
899 )))
900 }
901}
902impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
903 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
904 fmt.debug_list()
905 .entries(self.clone().map(FlattenErrorContext))
906 .finish()
907 }
908}
909impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
910 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
911 let mut fmt = f.debug_struct("Wgpeer");
912 for attr in self.clone() {
913 let attr = match attr {
914 Ok(a) => a,
915 Err(err) => {
916 fmt.finish()?;
917 f.write_str("Err(")?;
918 err.fmt(f)?;
919 return f.write_str(")");
920 }
921 };
922 match attr {
923 Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
924 Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
925 Wgpeer::Flags(val) => {
926 fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
927 }
928 Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
929 Wgpeer::PersistentKeepaliveInterval(val) => {
930 fmt.field("PersistentKeepaliveInterval", &val)
931 }
932 Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
933 Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
934 Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
935 Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
936 Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
937 };
938 }
939 fmt.finish()
940 }
941}
942impl IterableWgpeer<'_> {
943 pub fn lookup_attr(
944 &self,
945 offset: usize,
946 missing_type: Option<u16>,
947 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
948 let mut stack = Vec::new();
949 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
950 if missing_type.is_some() && cur == offset {
951 stack.push(("Wgpeer", offset));
952 return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
953 }
954 if cur > offset || cur + self.buf.len() < offset {
955 return (stack, None);
956 }
957 let mut attrs = self.clone();
958 let mut last_off = cur + attrs.pos;
959 let mut missing = None;
960 while let Some(attr) = attrs.next() {
961 let Ok(attr) = attr else { break };
962 match attr {
963 Wgpeer::PublicKey(val) => {
964 if last_off == offset {
965 stack.push(("PublicKey", last_off));
966 break;
967 }
968 }
969 Wgpeer::PresharedKey(val) => {
970 if last_off == offset {
971 stack.push(("PresharedKey", last_off));
972 break;
973 }
974 }
975 Wgpeer::Flags(val) => {
976 if last_off == offset {
977 stack.push(("Flags", last_off));
978 break;
979 }
980 }
981 Wgpeer::Endpoint(val) => {
982 if last_off == offset {
983 stack.push(("Endpoint", last_off));
984 break;
985 }
986 }
987 Wgpeer::PersistentKeepaliveInterval(val) => {
988 if last_off == offset {
989 stack.push(("PersistentKeepaliveInterval", last_off));
990 break;
991 }
992 }
993 Wgpeer::LastHandshakeTime(val) => {
994 if last_off == offset {
995 stack.push(("LastHandshakeTime", last_off));
996 break;
997 }
998 }
999 Wgpeer::RxBytes(val) => {
1000 if last_off == offset {
1001 stack.push(("RxBytes", last_off));
1002 break;
1003 }
1004 }
1005 Wgpeer::TxBytes(val) => {
1006 if last_off == offset {
1007 stack.push(("TxBytes", last_off));
1008 break;
1009 }
1010 }
1011 Wgpeer::Allowedips(val) => {
1012 for entry in val {
1013 let Ok(attr) = entry else { break };
1014 (stack, missing) = attr.lookup_attr(offset, missing_type);
1015 if !stack.is_empty() {
1016 break;
1017 }
1018 }
1019 if !stack.is_empty() {
1020 stack.push(("Allowedips", last_off));
1021 break;
1022 }
1023 }
1024 Wgpeer::ProtocolVersion(val) => {
1025 if last_off == offset {
1026 stack.push(("ProtocolVersion", last_off));
1027 break;
1028 }
1029 }
1030 _ => {}
1031 };
1032 last_off = cur + attrs.pos;
1033 }
1034 if !stack.is_empty() {
1035 stack.push(("Wgpeer", cur));
1036 }
1037 (stack, missing)
1038 }
1039}
1040#[derive(Clone)]
1041pub enum Wgallowedip {
1042 #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1043 Family(u16),
1044 #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1045 Ipaddr(std::net::IpAddr),
1046 CidrMask(u8),
1047 #[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)"]
1048 Flags(u32),
1049}
1050impl<'a> IterableWgallowedip<'a> {
1051 #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1052 pub fn get_family(&self) -> Result<u16, ErrorContext> {
1053 let mut iter = self.clone();
1054 iter.pos = 0;
1055 for attr in iter {
1056 if let Ok(Wgallowedip::Family(val)) = attr {
1057 return Ok(val);
1058 }
1059 }
1060 Err(ErrorContext::new_missing(
1061 "Wgallowedip",
1062 "Family",
1063 self.orig_loc,
1064 self.buf.as_ptr() as usize,
1065 ))
1066 }
1067 #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1068 pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
1069 let mut iter = self.clone();
1070 iter.pos = 0;
1071 for attr in iter {
1072 if let Ok(Wgallowedip::Ipaddr(val)) = attr {
1073 return Ok(val);
1074 }
1075 }
1076 Err(ErrorContext::new_missing(
1077 "Wgallowedip",
1078 "Ipaddr",
1079 self.orig_loc,
1080 self.buf.as_ptr() as usize,
1081 ))
1082 }
1083 pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
1084 let mut iter = self.clone();
1085 iter.pos = 0;
1086 for attr in iter {
1087 if let Ok(Wgallowedip::CidrMask(val)) = attr {
1088 return Ok(val);
1089 }
1090 }
1091 Err(ErrorContext::new_missing(
1092 "Wgallowedip",
1093 "CidrMask",
1094 self.orig_loc,
1095 self.buf.as_ptr() as usize,
1096 ))
1097 }
1098 #[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)"]
1099 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1100 let mut iter = self.clone();
1101 iter.pos = 0;
1102 for attr in iter {
1103 if let Ok(Wgallowedip::Flags(val)) = attr {
1104 return Ok(val);
1105 }
1106 }
1107 Err(ErrorContext::new_missing(
1108 "Wgallowedip",
1109 "Flags",
1110 self.orig_loc,
1111 self.buf.as_ptr() as usize,
1112 ))
1113 }
1114}
1115impl Wgallowedip {
1116 pub fn new<'a>(buf: &'a [u8]) -> IterableWgallowedip<'a> {
1117 IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1118 }
1119 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1120 let res = match r#type {
1121 0u16 => "Unspec",
1122 1u16 => "Family",
1123 2u16 => "Ipaddr",
1124 3u16 => "CidrMask",
1125 4u16 => "Flags",
1126 _ => return None,
1127 };
1128 Some(res)
1129 }
1130}
1131#[derive(Clone, Copy, Default)]
1132pub struct IterableWgallowedip<'a> {
1133 buf: &'a [u8],
1134 pos: usize,
1135 orig_loc: usize,
1136}
1137impl<'a> IterableWgallowedip<'a> {
1138 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1139 Self {
1140 buf,
1141 pos: 0,
1142 orig_loc,
1143 }
1144 }
1145 pub fn get_buf(&self) -> &'a [u8] {
1146 self.buf
1147 }
1148}
1149impl<'a> Iterator for IterableWgallowedip<'a> {
1150 type Item = Result<Wgallowedip, ErrorContext>;
1151 fn next(&mut self) -> Option<Self::Item> {
1152 let mut pos;
1153 let mut r#type;
1154 loop {
1155 pos = self.pos;
1156 r#type = None;
1157 if self.buf.len() == self.pos {
1158 return None;
1159 }
1160 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1161 self.pos = self.buf.len();
1162 break;
1163 };
1164 r#type = Some(header.r#type);
1165 let res = match header.r#type {
1166 1u16 => Wgallowedip::Family({
1167 let res = parse_u16(next);
1168 let Some(val) = res else { break };
1169 val
1170 }),
1171 2u16 => Wgallowedip::Ipaddr({
1172 let res = parse_ip(next);
1173 let Some(val) = res else { break };
1174 val
1175 }),
1176 3u16 => Wgallowedip::CidrMask({
1177 let res = parse_u8(next);
1178 let Some(val) = res else { break };
1179 val
1180 }),
1181 4u16 => Wgallowedip::Flags({
1182 let res = parse_u32(next);
1183 let Some(val) = res else { break };
1184 val
1185 }),
1186 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1187 n => continue,
1188 };
1189 return Some(Ok(res));
1190 }
1191 Some(Err(ErrorContext::new(
1192 "Wgallowedip",
1193 r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1194 self.orig_loc,
1195 self.buf.as_ptr().wrapping_add(pos) as usize,
1196 )))
1197 }
1198}
1199impl std::fmt::Debug for IterableWgallowedip<'_> {
1200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1201 let mut fmt = f.debug_struct("Wgallowedip");
1202 for attr in self.clone() {
1203 let attr = match attr {
1204 Ok(a) => a,
1205 Err(err) => {
1206 fmt.finish()?;
1207 f.write_str("Err(")?;
1208 err.fmt(f)?;
1209 return f.write_str(")");
1210 }
1211 };
1212 match attr {
1213 Wgallowedip::Family(val) => fmt.field("Family", &val),
1214 Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1215 Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1216 Wgallowedip::Flags(val) => fmt.field(
1217 "Flags",
1218 &FormatFlags(val.into(), WgallowedipFlags::from_value),
1219 ),
1220 };
1221 }
1222 fmt.finish()
1223 }
1224}
1225impl IterableWgallowedip<'_> {
1226 pub fn lookup_attr(
1227 &self,
1228 offset: usize,
1229 missing_type: Option<u16>,
1230 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1231 let mut stack = Vec::new();
1232 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1233 if missing_type.is_some() && cur == offset {
1234 stack.push(("Wgallowedip", offset));
1235 return (
1236 stack,
1237 missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1238 );
1239 }
1240 if cur > offset || cur + self.buf.len() < offset {
1241 return (stack, None);
1242 }
1243 let mut attrs = self.clone();
1244 let mut last_off = cur + attrs.pos;
1245 while let Some(attr) = attrs.next() {
1246 let Ok(attr) = attr else { break };
1247 match attr {
1248 Wgallowedip::Family(val) => {
1249 if last_off == offset {
1250 stack.push(("Family", last_off));
1251 break;
1252 }
1253 }
1254 Wgallowedip::Ipaddr(val) => {
1255 if last_off == offset {
1256 stack.push(("Ipaddr", last_off));
1257 break;
1258 }
1259 }
1260 Wgallowedip::CidrMask(val) => {
1261 if last_off == offset {
1262 stack.push(("CidrMask", last_off));
1263 break;
1264 }
1265 }
1266 Wgallowedip::Flags(val) => {
1267 if last_off == offset {
1268 stack.push(("Flags", last_off));
1269 break;
1270 }
1271 }
1272 _ => {}
1273 };
1274 last_off = cur + attrs.pos;
1275 }
1276 if !stack.is_empty() {
1277 stack.push(("Wgallowedip", cur));
1278 }
1279 (stack, None)
1280 }
1281}
1282pub struct PushWgdevice<Prev: Pusher> {
1283 pub(crate) prev: Option<Prev>,
1284 pub(crate) header_offset: Option<usize>,
1285}
1286impl<Prev: Pusher> Pusher for PushWgdevice<Prev> {
1287 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1288 self.prev.as_mut().unwrap().as_vec_mut()
1289 }
1290 fn as_vec(&self) -> &Vec<u8> {
1291 self.prev.as_ref().unwrap().as_vec()
1292 }
1293}
1294pub struct PushArrayWgpeer<Prev: Pusher> {
1295 pub(crate) prev: Option<Prev>,
1296 pub(crate) header_offset: Option<usize>,
1297 pub(crate) counter: u16,
1298}
1299impl<Prev: Pusher> Pusher for PushArrayWgpeer<Prev> {
1300 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1301 self.prev.as_mut().unwrap().as_vec_mut()
1302 }
1303 fn as_vec(&self) -> &Vec<u8> {
1304 self.prev.as_ref().unwrap().as_vec()
1305 }
1306}
1307impl<Prev: Pusher> PushArrayWgpeer<Prev> {
1308 pub fn new(prev: Prev) -> Self {
1309 Self {
1310 prev: Some(prev),
1311 header_offset: None,
1312 counter: 0,
1313 }
1314 }
1315 pub fn end_array(mut self) -> Prev {
1316 let mut prev = self.prev.take().unwrap();
1317 if let Some(header_offset) = &self.header_offset {
1318 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1319 }
1320 prev
1321 }
1322 pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1323 let index = self.counter;
1324 self.counter += 1;
1325 let header_offset = push_nested_header(self.as_vec_mut(), index);
1326 PushWgpeer {
1327 prev: Some(self),
1328 header_offset: Some(header_offset),
1329 }
1330 }
1331}
1332impl<Prev: Pusher> Drop for PushArrayWgpeer<Prev> {
1333 fn drop(&mut self) {
1334 if let Some(prev) = &mut self.prev {
1335 if let Some(header_offset) = &self.header_offset {
1336 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1337 }
1338 }
1339 }
1340}
1341impl<Prev: Pusher> PushWgdevice<Prev> {
1342 pub fn new(prev: Prev) -> Self {
1343 Self {
1344 prev: Some(prev),
1345 header_offset: None,
1346 }
1347 }
1348 pub fn end_nested(mut self) -> Prev {
1349 let mut prev = self.prev.take().unwrap();
1350 if let Some(header_offset) = &self.header_offset {
1351 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1352 }
1353 prev
1354 }
1355 pub fn push_ifindex(mut self, value: u32) -> Self {
1356 push_header(self.as_vec_mut(), 1u16, 4 as u16);
1357 self.as_vec_mut().extend(value.to_ne_bytes());
1358 self
1359 }
1360 pub fn push_ifname(mut self, value: &CStr) -> Self {
1361 push_header(
1362 self.as_vec_mut(),
1363 2u16,
1364 value.to_bytes_with_nul().len() as u16,
1365 );
1366 self.as_vec_mut().extend(value.to_bytes_with_nul());
1367 self
1368 }
1369 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1370 push_header(self.as_vec_mut(), 2u16, (value.len() + 1) as u16);
1371 self.as_vec_mut().extend(value);
1372 self.as_vec_mut().push(0);
1373 self
1374 }
1375 #[doc = "Set to all zeros to remove.\n"]
1376 pub fn push_private_key(mut self, value: &[u8]) -> Self {
1377 push_header(self.as_vec_mut(), 3u16, value.len() as u16);
1378 self.as_vec_mut().extend(value);
1379 self
1380 }
1381 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1382 push_header(self.as_vec_mut(), 4u16, value.len() as u16);
1383 self.as_vec_mut().extend(value);
1384 self
1385 }
1386 #[doc = "`0` or `WGDEVICE_F_REPLACE_PEERS` if all current peers should be removed\nprior to adding the list below.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
1387 pub fn push_flags(mut self, value: u32) -> Self {
1388 push_header(self.as_vec_mut(), 5u16, 4 as u16);
1389 self.as_vec_mut().extend(value.to_ne_bytes());
1390 self
1391 }
1392 #[doc = "Set as `0` to choose randomly.\n"]
1393 pub fn push_listen_port(mut self, value: u16) -> Self {
1394 push_header(self.as_vec_mut(), 6u16, 2 as u16);
1395 self.as_vec_mut().extend(value.to_ne_bytes());
1396 self
1397 }
1398 #[doc = "Set as `0` to disable.\n"]
1399 pub fn push_fwmark(mut self, value: u32) -> Self {
1400 push_header(self.as_vec_mut(), 7u16, 4 as u16);
1401 self.as_vec_mut().extend(value.to_ne_bytes());
1402 self
1403 }
1404 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
1405 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1406 let header_offset = push_nested_header(self.as_vec_mut(), 8u16);
1407 PushArrayWgpeer {
1408 prev: Some(self),
1409 header_offset: Some(header_offset),
1410 counter: 0,
1411 }
1412 }
1413}
1414impl<Prev: Pusher> Drop for PushWgdevice<Prev> {
1415 fn drop(&mut self) {
1416 if let Some(prev) = &mut self.prev {
1417 if let Some(header_offset) = &self.header_offset {
1418 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1419 }
1420 }
1421 }
1422}
1423pub struct PushWgpeer<Prev: Pusher> {
1424 pub(crate) prev: Option<Prev>,
1425 pub(crate) header_offset: Option<usize>,
1426}
1427impl<Prev: Pusher> Pusher for PushWgpeer<Prev> {
1428 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1429 self.prev.as_mut().unwrap().as_vec_mut()
1430 }
1431 fn as_vec(&self) -> &Vec<u8> {
1432 self.prev.as_ref().unwrap().as_vec()
1433 }
1434}
1435pub struct PushArrayWgallowedip<Prev: Pusher> {
1436 pub(crate) prev: Option<Prev>,
1437 pub(crate) header_offset: Option<usize>,
1438 pub(crate) counter: u16,
1439}
1440impl<Prev: Pusher> Pusher for PushArrayWgallowedip<Prev> {
1441 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1442 self.prev.as_mut().unwrap().as_vec_mut()
1443 }
1444 fn as_vec(&self) -> &Vec<u8> {
1445 self.prev.as_ref().unwrap().as_vec()
1446 }
1447}
1448impl<Prev: Pusher> PushArrayWgallowedip<Prev> {
1449 pub fn new(prev: Prev) -> Self {
1450 Self {
1451 prev: Some(prev),
1452 header_offset: None,
1453 counter: 0,
1454 }
1455 }
1456 pub fn end_array(mut self) -> Prev {
1457 let mut prev = self.prev.take().unwrap();
1458 if let Some(header_offset) = &self.header_offset {
1459 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1460 }
1461 prev
1462 }
1463 pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1464 let index = self.counter;
1465 self.counter += 1;
1466 let header_offset = push_nested_header(self.as_vec_mut(), index);
1467 PushWgallowedip {
1468 prev: Some(self),
1469 header_offset: Some(header_offset),
1470 }
1471 }
1472}
1473impl<Prev: Pusher> Drop for PushArrayWgallowedip<Prev> {
1474 fn drop(&mut self) {
1475 if let Some(prev) = &mut self.prev {
1476 if let Some(header_offset) = &self.header_offset {
1477 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1478 }
1479 }
1480 }
1481}
1482impl<Prev: Pusher> PushWgpeer<Prev> {
1483 pub fn new(prev: Prev) -> Self {
1484 Self {
1485 prev: Some(prev),
1486 header_offset: None,
1487 }
1488 }
1489 pub fn end_nested(mut self) -> Prev {
1490 let mut prev = self.prev.take().unwrap();
1491 if let Some(header_offset) = &self.header_offset {
1492 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1493 }
1494 prev
1495 }
1496 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1497 push_header(self.as_vec_mut(), 1u16, value.len() as u16);
1498 self.as_vec_mut().extend(value);
1499 self
1500 }
1501 #[doc = "Set as all zeros to remove.\n"]
1502 pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1503 push_header(self.as_vec_mut(), 2u16, value.len() as u16);
1504 self.as_vec_mut().extend(value);
1505 self
1506 }
1507 #[doc = "`0` and/or `WGPEER_F_REMOVE_ME` if the specified peer should not exist\nat the end of the operation, rather than added/updated and/or\n`WGPEER_F_REPLACE_ALLOWEDIPS` if all current allowed IPs of this peer\nshould be removed prior to adding the list below and/or\n`WGPEER_F_UPDATE_ONLY` if the peer should only be set if it already\nexists.\n\nAssociated type: [`WgpeerFlags`] (enum)"]
1508 pub fn push_flags(mut self, value: u32) -> Self {
1509 push_header(self.as_vec_mut(), 3u16, 4 as u16);
1510 self.as_vec_mut().extend(value.to_ne_bytes());
1511 self
1512 }
1513 #[doc = "struct sockaddr_in or struct sockaddr_in6\n"]
1514 pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1515 push_header(self.as_vec_mut(), 4u16, {
1516 match &value {
1517 SocketAddr::V4(_) => 16,
1518 SocketAddr::V6(_) => 28,
1519 }
1520 } as u16);
1521 encode_sockaddr(self.as_vec_mut(), value);
1522 self
1523 }
1524 #[doc = "Set as `0` to disable.\n"]
1525 pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1526 push_header(self.as_vec_mut(), 5u16, 2 as u16);
1527 self.as_vec_mut().extend(value.to_ne_bytes());
1528 self
1529 }
1530 pub fn push_last_handshake_time(mut self, value: KernelTimespec) -> Self {
1531 push_header(self.as_vec_mut(), 6u16, value.as_slice().len() as u16);
1532 self.as_vec_mut().extend(value.as_slice());
1533 self
1534 }
1535 pub fn push_rx_bytes(mut self, value: u64) -> Self {
1536 push_header(self.as_vec_mut(), 7u16, 8 as u16);
1537 self.as_vec_mut().extend(value.to_ne_bytes());
1538 self
1539 }
1540 pub fn push_tx_bytes(mut self, value: u64) -> Self {
1541 push_header(self.as_vec_mut(), 8u16, 8 as u16);
1542 self.as_vec_mut().extend(value.to_ne_bytes());
1543 self
1544 }
1545 #[doc = "The index/type parameter is unused on `SET_DEVICE` operations and is\nzero on `GET_DEVICE` operations.\n"]
1546 pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1547 let header_offset = push_nested_header(self.as_vec_mut(), 9u16);
1548 PushArrayWgallowedip {
1549 prev: Some(self),
1550 header_offset: Some(header_offset),
1551 counter: 0,
1552 }
1553 }
1554 #[doc = "Should not be set or used at all by most users of this API, as the most\nrecent protocol will be used when this is unset. Otherwise, must be set\nto `1`.\n"]
1555 pub fn push_protocol_version(mut self, value: u32) -> Self {
1556 push_header(self.as_vec_mut(), 10u16, 4 as u16);
1557 self.as_vec_mut().extend(value.to_ne_bytes());
1558 self
1559 }
1560}
1561impl<Prev: Pusher> Drop for PushWgpeer<Prev> {
1562 fn drop(&mut self) {
1563 if let Some(prev) = &mut self.prev {
1564 if let Some(header_offset) = &self.header_offset {
1565 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1566 }
1567 }
1568 }
1569}
1570pub struct PushWgallowedip<Prev: Pusher> {
1571 pub(crate) prev: Option<Prev>,
1572 pub(crate) header_offset: Option<usize>,
1573}
1574impl<Prev: Pusher> Pusher for PushWgallowedip<Prev> {
1575 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
1576 self.prev.as_mut().unwrap().as_vec_mut()
1577 }
1578 fn as_vec(&self) -> &Vec<u8> {
1579 self.prev.as_ref().unwrap().as_vec()
1580 }
1581}
1582impl<Prev: Pusher> PushWgallowedip<Prev> {
1583 pub fn new(prev: Prev) -> Self {
1584 Self {
1585 prev: Some(prev),
1586 header_offset: None,
1587 }
1588 }
1589 pub fn end_nested(mut self) -> Prev {
1590 let mut prev = self.prev.take().unwrap();
1591 if let Some(header_offset) = &self.header_offset {
1592 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1593 }
1594 prev
1595 }
1596 #[doc = "IP family, either `AF_INET` or `AF_INET6`.\n"]
1597 pub fn push_family(mut self, value: u16) -> Self {
1598 push_header(self.as_vec_mut(), 1u16, 2 as u16);
1599 self.as_vec_mut().extend(value.to_ne_bytes());
1600 self
1601 }
1602 #[doc = "Either `struct in_addr` or `struct in6_addr`.\n"]
1603 pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1604 push_header(self.as_vec_mut(), 2u16, {
1605 match &value {
1606 IpAddr::V4(_) => 4,
1607 IpAddr::V6(_) => 16,
1608 }
1609 } as u16);
1610 encode_ip(self.as_vec_mut(), value);
1611 self
1612 }
1613 pub fn push_cidr_mask(mut self, value: u8) -> Self {
1614 push_header(self.as_vec_mut(), 3u16, 1 as u16);
1615 self.as_vec_mut().extend(value.to_ne_bytes());
1616 self
1617 }
1618 #[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)"]
1619 pub fn push_flags(mut self, value: u32) -> Self {
1620 push_header(self.as_vec_mut(), 4u16, 4 as u16);
1621 self.as_vec_mut().extend(value.to_ne_bytes());
1622 self
1623 }
1624}
1625impl<Prev: Pusher> Drop for PushWgallowedip<Prev> {
1626 fn drop(&mut self) {
1627 if let Some(prev) = &mut self.prev {
1628 if let Some(header_offset) = &self.header_offset {
1629 finalize_nested_header(prev.as_vec_mut(), *header_offset);
1630 }
1631 }
1632 }
1633}
1634#[doc = "# Retrieve WireGuard device\n\nThe command should be called with one but not both of:\n\n- `WGDEVICE_A_IFINDEX`\n- `WGDEVICE_A_IFNAME`\n\nThe kernel will then return several messages (`NLM_F_MULTI`). It is\npossible that all of the allowed IPs of a single peer will not fit\nwithin a single netlink message. In that case, the same peer will be\nwritten in the following message, except it will only contain\n`WGPEER_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 in\nfollowing messages, except those will only contain `WGDEVICE_A_IFNAME`\nand `WGDEVICE_A_PEERS`. It is then up to the receiver to coalesce these\nmessages to form the complete list of peers.\n\nSince this is an `NLA_F_DUMP` command, the final message will always be\n`NLMSG_DONE`, even if an error occurs. However, this `NLMSG_DONE`\nmessage contains an integer error code. It is either zero or a negative\nerror code corresponding to the errno.\n\nFlags: uns-admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n\nReply attributes:\n- [.get_ifindex()](IterableWgdevice::get_ifindex)\n- [.get_ifname()](IterableWgdevice::get_ifname)\n- [.get_private_key()](IterableWgdevice::get_private_key)\n- [.get_public_key()](IterableWgdevice::get_public_key)\n- [.get_flags()](IterableWgdevice::get_flags)\n- [.get_listen_port()](IterableWgdevice::get_listen_port)\n- [.get_fwmark()](IterableWgdevice::get_fwmark)\n- [.get_peers()](IterableWgdevice::get_peers)\n\n"]
1635#[derive(Debug)]
1636pub struct OpGetDeviceDump<'r> {
1637 request: Request<'r>,
1638}
1639impl<'r> OpGetDeviceDump<'r> {
1640 pub fn new(mut request: Request<'r>) -> Self {
1641 Self::write_header(request.buf_mut());
1642 Self {
1643 request: request.set_dump(),
1644 }
1645 }
1646 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1647 Self::write_header(buf);
1648 PushWgdevice::new(buf)
1649 }
1650 pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1651 PushWgdevice::new(self.request.buf_mut())
1652 }
1653 pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1654 PushWgdevice::new(self.request.buf)
1655 }
1656 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1657 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1658 IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1659 }
1660 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1661 let mut header = BuiltinNfgenmsg::new();
1662 header.cmd = 0u8;
1663 header.version = 1u8;
1664 prev.as_vec_mut().extend(header.as_slice());
1665 }
1666}
1667impl NetlinkRequest for OpGetDeviceDump<'_> {
1668 fn protocol(&self) -> Protocol {
1669 Protocol::Generic("wireguard".as_bytes())
1670 }
1671 fn flags(&self) -> u16 {
1672 self.request.flags
1673 }
1674 fn payload(&self) -> &[u8] {
1675 self.request.buf()
1676 }
1677 type ReplyType<'buf> = IterableWgdevice<'buf>;
1678 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1679 Self::decode_request(buf)
1680 }
1681 fn lookup(
1682 buf: &[u8],
1683 offset: usize,
1684 missing_type: Option<u16>,
1685 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1686 Self::decode_request(buf).lookup_attr(offset, missing_type)
1687 }
1688}
1689#[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 the\nmaximum message length accepted by the kernel. In that case, several\nmessages should be sent one after another, with each successive one\nfilling in information not contained in the prior. Note that if\n`WGDEVICE_F_REPLACE_PEERS` is specified in the first message, it\nprobably should not be specified in fragments that come after, so that\nthe list of peers is only cleared the first time but appended after.\nLikewise for peers, if `WGPEER_F_REPLACE_ALLOWEDIPS` is specified in the\nfirst message of a peer, it likely should not be specified in subsequent\nfragments.\n\nIf an error occurs, `NLMSG_ERROR` will reply containing an errno.\n\nFlags: uns-admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n- [.push_private_key()](PushWgdevice::push_private_key)\n- [.push_public_key()](PushWgdevice::push_public_key)\n- [.push_flags()](PushWgdevice::push_flags)\n- [.push_listen_port()](PushWgdevice::push_listen_port)\n- [.push_fwmark()](PushWgdevice::push_fwmark)\n- [.array_peers()](PushWgdevice::array_peers)\n\n"]
1690#[derive(Debug)]
1691pub struct OpSetDeviceDo<'r> {
1692 request: Request<'r>,
1693}
1694impl<'r> OpSetDeviceDo<'r> {
1695 pub fn new(mut request: Request<'r>) -> Self {
1696 Self::write_header(request.buf_mut());
1697 Self { request: request }
1698 }
1699 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1700 Self::write_header(buf);
1701 PushWgdevice::new(buf)
1702 }
1703 pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1704 PushWgdevice::new(self.request.buf_mut())
1705 }
1706 pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1707 PushWgdevice::new(self.request.buf)
1708 }
1709 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1710 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1711 IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1712 }
1713 fn write_header<Prev: Pusher>(prev: &mut Prev) {
1714 let mut header = BuiltinNfgenmsg::new();
1715 header.cmd = 1u8;
1716 header.version = 1u8;
1717 prev.as_vec_mut().extend(header.as_slice());
1718 }
1719}
1720impl NetlinkRequest for OpSetDeviceDo<'_> {
1721 fn protocol(&self) -> Protocol {
1722 Protocol::Generic("wireguard".as_bytes())
1723 }
1724 fn flags(&self) -> u16 {
1725 self.request.flags
1726 }
1727 fn payload(&self) -> &[u8] {
1728 self.request.buf()
1729 }
1730 type ReplyType<'buf> = IterableWgdevice<'buf>;
1731 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1732 Self::decode_request(buf)
1733 }
1734 fn lookup(
1735 buf: &[u8],
1736 offset: usize,
1737 missing_type: Option<u16>,
1738 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1739 Self::decode_request(buf).lookup_attr(offset, missing_type)
1740 }
1741}
1742use crate::traits::LookupFn;
1743use crate::utils::RequestBuf;
1744#[derive(Debug)]
1745pub struct Request<'buf> {
1746 buf: RequestBuf<'buf>,
1747 flags: u16,
1748 writeback: Option<&'buf mut Option<RequestInfo>>,
1749}
1750#[allow(unused)]
1751#[derive(Debug, Clone)]
1752pub struct RequestInfo {
1753 protocol: Protocol,
1754 flags: u16,
1755 name: &'static str,
1756 lookup: LookupFn,
1757}
1758impl Request<'static> {
1759 pub fn new() -> Self {
1760 Self::new_from_buf(Vec::new())
1761 }
1762 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1763 Self {
1764 flags: 0,
1765 buf: RequestBuf::Own(buf),
1766 writeback: None,
1767 }
1768 }
1769 pub fn into_buf(self) -> Vec<u8> {
1770 match self.buf {
1771 RequestBuf::Own(buf) => buf,
1772 _ => unreachable!(),
1773 }
1774 }
1775}
1776impl<'buf> Request<'buf> {
1777 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1778 buf.clear();
1779 Self::new_extend(buf)
1780 }
1781 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1782 Self {
1783 flags: 0,
1784 buf: RequestBuf::Ref(buf),
1785 writeback: None,
1786 }
1787 }
1788 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1789 let Some(writeback) = &mut self.writeback else {
1790 return;
1791 };
1792 **writeback = Some(RequestInfo {
1793 protocol,
1794 flags: self.flags,
1795 name,
1796 lookup,
1797 })
1798 }
1799 pub fn buf(&self) -> &Vec<u8> {
1800 self.buf.buf()
1801 }
1802 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1803 self.buf.buf_mut()
1804 }
1805 #[doc = "Set `NLM_F_CREATE` flag"]
1806 pub fn set_create(mut self) -> Self {
1807 self.flags |= consts::NLM_F_CREATE as u16;
1808 self
1809 }
1810 #[doc = "Set `NLM_F_EXCL` flag"]
1811 pub fn set_excl(mut self) -> Self {
1812 self.flags |= consts::NLM_F_EXCL as u16;
1813 self
1814 }
1815 #[doc = "Set `NLM_F_REPLACE` flag"]
1816 pub fn set_replace(mut self) -> Self {
1817 self.flags |= consts::NLM_F_REPLACE as u16;
1818 self
1819 }
1820 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1821 pub fn set_change(self) -> Self {
1822 self.set_create().set_replace()
1823 }
1824 #[doc = "Set `NLM_F_APPEND` flag"]
1825 pub fn set_append(mut self) -> Self {
1826 self.flags |= consts::NLM_F_APPEND as u16;
1827 self
1828 }
1829 #[doc = "Set `self.flags |= flags`"]
1830 pub fn set_flags(mut self, flags: u16) -> Self {
1831 self.flags |= flags;
1832 self
1833 }
1834 #[doc = "Set `self.flags ^= self.flags & flags`"]
1835 pub fn unset_flags(mut self, flags: u16) -> Self {
1836 self.flags ^= self.flags & flags;
1837 self
1838 }
1839 #[doc = "Set `NLM_F_DUMP` flag"]
1840 fn set_dump(mut self) -> Self {
1841 self.flags |= consts::NLM_F_DUMP as u16;
1842 self
1843 }
1844 #[doc = "# Retrieve WireGuard device\n\nThe command should be called with one but not both of:\n\n- `WGDEVICE_A_IFINDEX`\n- `WGDEVICE_A_IFNAME`\n\nThe kernel will then return several messages (`NLM_F_MULTI`). It is\npossible that all of the allowed IPs of a single peer will not fit\nwithin a single netlink message. In that case, the same peer will be\nwritten in the following message, except it will only contain\n`WGPEER_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 in\nfollowing messages, except those will only contain `WGDEVICE_A_IFNAME`\nand `WGDEVICE_A_PEERS`. It is then up to the receiver to coalesce these\nmessages to form the complete list of peers.\n\nSince this is an `NLA_F_DUMP` command, the final message will always be\n`NLMSG_DONE`, even if an error occurs. However, this `NLMSG_DONE`\nmessage contains an integer error code. It is either zero or a negative\nerror code corresponding to the errno.\n\nFlags: uns-admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n\nReply attributes:\n- [.get_ifindex()](IterableWgdevice::get_ifindex)\n- [.get_ifname()](IterableWgdevice::get_ifname)\n- [.get_private_key()](IterableWgdevice::get_private_key)\n- [.get_public_key()](IterableWgdevice::get_public_key)\n- [.get_flags()](IterableWgdevice::get_flags)\n- [.get_listen_port()](IterableWgdevice::get_listen_port)\n- [.get_fwmark()](IterableWgdevice::get_fwmark)\n- [.get_peers()](IterableWgdevice::get_peers)\n\n"]
1845 pub fn op_get_device_dump(self) -> OpGetDeviceDump<'buf> {
1846 let mut res = OpGetDeviceDump::new(self);
1847 res.request.do_writeback(
1848 res.protocol(),
1849 "op-get-device-dump",
1850 OpGetDeviceDump::lookup,
1851 );
1852 res
1853 }
1854 #[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 the\nmaximum message length accepted by the kernel. In that case, several\nmessages should be sent one after another, with each successive one\nfilling in information not contained in the prior. Note that if\n`WGDEVICE_F_REPLACE_PEERS` is specified in the first message, it\nprobably should not be specified in fragments that come after, so that\nthe list of peers is only cleared the first time but appended after.\nLikewise for peers, if `WGPEER_F_REPLACE_ALLOWEDIPS` is specified in the\nfirst message of a peer, it likely should not be specified in subsequent\nfragments.\n\nIf an error occurs, `NLMSG_ERROR` will reply containing an errno.\n\nFlags: uns-admin-perm\n\nRequest attributes:\n- [.push_ifindex()](PushWgdevice::push_ifindex)\n- [.push_ifname()](PushWgdevice::push_ifname)\n- [.push_private_key()](PushWgdevice::push_private_key)\n- [.push_public_key()](PushWgdevice::push_public_key)\n- [.push_flags()](PushWgdevice::push_flags)\n- [.push_listen_port()](PushWgdevice::push_listen_port)\n- [.push_fwmark()](PushWgdevice::push_fwmark)\n- [.array_peers()](PushWgdevice::array_peers)\n\n"]
1855 pub fn op_set_device_do(self) -> OpSetDeviceDo<'buf> {
1856 let mut res = OpSetDeviceDo::new(self);
1857 res.request
1858 .do_writeback(res.protocol(), "op-set-device-do", OpSetDeviceDo::lookup);
1859 res
1860 }
1861}
1862#[cfg(test)]
1863mod generated_tests {
1864 use super::*;
1865 #[test]
1866 fn tests() {
1867 let _ = IterableWgdevice::get_flags;
1868 let _ = IterableWgdevice::get_fwmark;
1869 let _ = IterableWgdevice::get_ifindex;
1870 let _ = IterableWgdevice::get_ifname;
1871 let _ = IterableWgdevice::get_listen_port;
1872 let _ = IterableWgdevice::get_peers;
1873 let _ = IterableWgdevice::get_private_key;
1874 let _ = IterableWgdevice::get_public_key;
1875 let _ = PushWgdevice::<&mut Vec<u8>>::array_peers;
1876 let _ = PushWgdevice::<&mut Vec<u8>>::push_flags;
1877 let _ = PushWgdevice::<&mut Vec<u8>>::push_fwmark;
1878 let _ = PushWgdevice::<&mut Vec<u8>>::push_ifindex;
1879 let _ = PushWgdevice::<&mut Vec<u8>>::push_ifname;
1880 let _ = PushWgdevice::<&mut Vec<u8>>::push_listen_port;
1881 let _ = PushWgdevice::<&mut Vec<u8>>::push_private_key;
1882 let _ = PushWgdevice::<&mut Vec<u8>>::push_public_key;
1883 }
1884}