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\ndefines two commands: get and set\\. Note that while they share many common\nattributes, these two commands actually accept a slightly different set of\ninputs and outputs\\. These differences are noted under the individual\nattributes\\.\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\\."]
67 pub sec: u64,
68 #[doc = "Number of nanoseconds, after the second began\\."]
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\\."]
145 PrivateKey(&'a [u8]),
146 PublicKey(&'a [u8]),
147 #[doc = "\\`\\`0\\`\\` or \\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` if all current peers should be\nremoved prior to adding the list below\\.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
148 Flags(u32),
149 #[doc = "Set as \\`\\`0\\`\\` to choose randomly\\."]
150 ListenPort(u16),
151 #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
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 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 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\\."]
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 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 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\nremoved prior 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 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\\."]
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 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\\."]
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 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 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 Some(Err(ErrorContext::new(
318 "Wgpeer",
319 None,
320 self.orig_loc,
321 self.buf.as_ptr().wrapping_add(self.pos) as usize,
322 )))
323 }
324}
325impl Wgdevice<'_> {
326 pub fn new<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
327 IterableWgdevice::with_loc(buf, buf.as_ptr() as usize)
328 }
329 fn attr_from_type(r#type: u16) -> Option<&'static str> {
330 let res = match r#type {
331 0u16 => "Unspec",
332 1u16 => "Ifindex",
333 2u16 => "Ifname",
334 3u16 => "PrivateKey",
335 4u16 => "PublicKey",
336 5u16 => "Flags",
337 6u16 => "ListenPort",
338 7u16 => "Fwmark",
339 8u16 => "Peers",
340 _ => return None,
341 };
342 Some(res)
343 }
344}
345#[derive(Clone, Copy, Default)]
346pub struct IterableWgdevice<'a> {
347 buf: &'a [u8],
348 pos: usize,
349 orig_loc: usize,
350}
351impl<'a> IterableWgdevice<'a> {
352 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
353 Self {
354 buf,
355 pos: 0,
356 orig_loc,
357 }
358 }
359 pub fn get_buf(&self) -> &'a [u8] {
360 self.buf
361 }
362}
363impl<'a> Iterator for IterableWgdevice<'a> {
364 type Item = Result<Wgdevice<'a>, ErrorContext>;
365 fn next(&mut self) -> Option<Self::Item> {
366 let pos = self.pos;
367 let mut r#type;
368 loop {
369 r#type = None;
370 if self.buf.len() == self.pos {
371 return None;
372 }
373 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
374 break;
375 };
376 r#type = Some(header.r#type);
377 let res = match header.r#type {
378 1u16 => Wgdevice::Ifindex({
379 let res = parse_u32(next);
380 let Some(val) = res else { break };
381 val
382 }),
383 2u16 => Wgdevice::Ifname({
384 let res = CStr::from_bytes_with_nul(next).ok();
385 let Some(val) = res else { break };
386 val
387 }),
388 3u16 => Wgdevice::PrivateKey({
389 let res = Some(next);
390 let Some(val) = res else { break };
391 val
392 }),
393 4u16 => Wgdevice::PublicKey({
394 let res = Some(next);
395 let Some(val) = res else { break };
396 val
397 }),
398 5u16 => Wgdevice::Flags({
399 let res = parse_u32(next);
400 let Some(val) = res else { break };
401 val
402 }),
403 6u16 => Wgdevice::ListenPort({
404 let res = parse_u16(next);
405 let Some(val) = res else { break };
406 val
407 }),
408 7u16 => Wgdevice::Fwmark({
409 let res = parse_u32(next);
410 let Some(val) = res else { break };
411 val
412 }),
413 8u16 => Wgdevice::Peers({
414 let res = Some(IterableArrayWgpeer::with_loc(next, self.orig_loc));
415 let Some(val) = res else { break };
416 val
417 }),
418 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
419 n => continue,
420 };
421 return Some(Ok(res));
422 }
423 Some(Err(ErrorContext::new(
424 "Wgdevice",
425 r#type.and_then(|t| Wgdevice::attr_from_type(t)),
426 self.orig_loc,
427 self.buf.as_ptr().wrapping_add(pos) as usize,
428 )))
429 }
430}
431impl std::fmt::Debug for IterableArrayWgpeer<'_> {
432 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
433 fmt.debug_list()
434 .entries(self.clone().map(FlattenErrorContext))
435 .finish()
436 }
437}
438impl<'a> std::fmt::Debug for IterableWgdevice<'_> {
439 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
440 let mut fmt = f.debug_struct("Wgdevice");
441 for attr in self.clone() {
442 let attr = match attr {
443 Ok(a) => a,
444 Err(err) => {
445 fmt.finish()?;
446 f.write_str("Err(")?;
447 err.fmt(f)?;
448 return f.write_str(")");
449 }
450 };
451 match attr {
452 Wgdevice::Ifindex(val) => fmt.field("Ifindex", &val),
453 Wgdevice::Ifname(val) => fmt.field("Ifname", &val),
454 Wgdevice::PrivateKey(val) => fmt.field("PrivateKey", &FormatHex(val)),
455 Wgdevice::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
456 Wgdevice::Flags(val) => {
457 fmt.field("Flags", &FormatFlags(val.into(), WgdeviceFlags::from_value))
458 }
459 Wgdevice::ListenPort(val) => fmt.field("ListenPort", &val),
460 Wgdevice::Fwmark(val) => fmt.field("Fwmark", &val),
461 Wgdevice::Peers(val) => fmt.field("Peers", &val),
462 };
463 }
464 fmt.finish()
465 }
466}
467impl IterableWgdevice<'_> {
468 pub fn lookup_attr(
469 &self,
470 offset: usize,
471 missing_type: Option<u16>,
472 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
473 let mut stack = Vec::new();
474 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
475 if missing_type.is_some() && cur == offset {
476 stack.push(("Wgdevice", offset));
477 return (
478 stack,
479 missing_type.and_then(|t| Wgdevice::attr_from_type(t)),
480 );
481 }
482 if cur > offset || cur + self.buf.len() < offset {
483 return (stack, None);
484 }
485 let mut attrs = self.clone();
486 let mut last_off = cur + attrs.pos;
487 let mut missing = None;
488 while let Some(attr) = attrs.next() {
489 let Ok(attr) = attr else { break };
490 match attr {
491 Wgdevice::Ifindex(val) => {
492 if last_off == offset {
493 stack.push(("Ifindex", last_off));
494 break;
495 }
496 }
497 Wgdevice::Ifname(val) => {
498 if last_off == offset {
499 stack.push(("Ifname", last_off));
500 break;
501 }
502 }
503 Wgdevice::PrivateKey(val) => {
504 if last_off == offset {
505 stack.push(("PrivateKey", last_off));
506 break;
507 }
508 }
509 Wgdevice::PublicKey(val) => {
510 if last_off == offset {
511 stack.push(("PublicKey", last_off));
512 break;
513 }
514 }
515 Wgdevice::Flags(val) => {
516 if last_off == offset {
517 stack.push(("Flags", last_off));
518 break;
519 }
520 }
521 Wgdevice::ListenPort(val) => {
522 if last_off == offset {
523 stack.push(("ListenPort", last_off));
524 break;
525 }
526 }
527 Wgdevice::Fwmark(val) => {
528 if last_off == offset {
529 stack.push(("Fwmark", last_off));
530 break;
531 }
532 }
533 Wgdevice::Peers(val) => {
534 for entry in val {
535 let Ok(attr) = entry else { break };
536 (stack, missing) = attr.lookup_attr(offset, missing_type);
537 if !stack.is_empty() {
538 break;
539 }
540 }
541 if !stack.is_empty() {
542 stack.push(("Peers", last_off));
543 break;
544 }
545 }
546 _ => {}
547 };
548 last_off = cur + attrs.pos;
549 }
550 if !stack.is_empty() {
551 stack.push(("Wgdevice", cur));
552 }
553 (stack, missing)
554 }
555}
556#[derive(Clone)]
557pub enum Wgpeer<'a> {
558 PublicKey(&'a [u8]),
559 #[doc = "Set as all zeros to remove\\."]
560 PresharedKey(&'a [u8]),
561 #[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 and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should 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)"]
562 Flags(u32),
563 #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
564 Endpoint(std::net::SocketAddr),
565 #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
566 PersistentKeepaliveInterval(u16),
567 LastHandshakeTime(KernelTimespec),
568 RxBytes(u64),
569 TxBytes(u64),
570 #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
571 Allowedips(IterableArrayWgallowedip<'a>),
572 #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
573 ProtocolVersion(u32),
574}
575impl<'a> IterableWgpeer<'a> {
576 pub fn get_public_key(&self) -> Result<&'a [u8], ErrorContext> {
577 let mut iter = self.clone();
578 iter.pos = 0;
579 for attr in iter {
580 if let Wgpeer::PublicKey(val) = attr? {
581 return Ok(val);
582 }
583 }
584 Err(ErrorContext::new_missing(
585 "Wgpeer",
586 "PublicKey",
587 self.orig_loc,
588 self.buf.as_ptr() as usize,
589 ))
590 }
591 #[doc = "Set as all zeros to remove\\."]
592 pub fn get_preshared_key(&self) -> Result<&'a [u8], ErrorContext> {
593 let mut iter = self.clone();
594 iter.pos = 0;
595 for attr in iter {
596 if let Wgpeer::PresharedKey(val) = attr? {
597 return Ok(val);
598 }
599 }
600 Err(ErrorContext::new_missing(
601 "Wgpeer",
602 "PresharedKey",
603 self.orig_loc,
604 self.buf.as_ptr() as usize,
605 ))
606 }
607 #[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 and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should 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)"]
608 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
609 let mut iter = self.clone();
610 iter.pos = 0;
611 for attr in iter {
612 if let Wgpeer::Flags(val) = attr? {
613 return Ok(val);
614 }
615 }
616 Err(ErrorContext::new_missing(
617 "Wgpeer",
618 "Flags",
619 self.orig_loc,
620 self.buf.as_ptr() as usize,
621 ))
622 }
623 #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
624 pub fn get_endpoint(&self) -> Result<std::net::SocketAddr, ErrorContext> {
625 let mut iter = self.clone();
626 iter.pos = 0;
627 for attr in iter {
628 if let Wgpeer::Endpoint(val) = attr? {
629 return Ok(val);
630 }
631 }
632 Err(ErrorContext::new_missing(
633 "Wgpeer",
634 "Endpoint",
635 self.orig_loc,
636 self.buf.as_ptr() as usize,
637 ))
638 }
639 #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
640 pub fn get_persistent_keepalive_interval(&self) -> Result<u16, ErrorContext> {
641 let mut iter = self.clone();
642 iter.pos = 0;
643 for attr in iter {
644 if let Wgpeer::PersistentKeepaliveInterval(val) = attr? {
645 return Ok(val);
646 }
647 }
648 Err(ErrorContext::new_missing(
649 "Wgpeer",
650 "PersistentKeepaliveInterval",
651 self.orig_loc,
652 self.buf.as_ptr() as usize,
653 ))
654 }
655 pub fn get_last_handshake_time(&self) -> Result<KernelTimespec, ErrorContext> {
656 let mut iter = self.clone();
657 iter.pos = 0;
658 for attr in iter {
659 if let Wgpeer::LastHandshakeTime(val) = attr? {
660 return Ok(val);
661 }
662 }
663 Err(ErrorContext::new_missing(
664 "Wgpeer",
665 "LastHandshakeTime",
666 self.orig_loc,
667 self.buf.as_ptr() as usize,
668 ))
669 }
670 pub fn get_rx_bytes(&self) -> Result<u64, ErrorContext> {
671 let mut iter = self.clone();
672 iter.pos = 0;
673 for attr in iter {
674 if let Wgpeer::RxBytes(val) = attr? {
675 return Ok(val);
676 }
677 }
678 Err(ErrorContext::new_missing(
679 "Wgpeer",
680 "RxBytes",
681 self.orig_loc,
682 self.buf.as_ptr() as usize,
683 ))
684 }
685 pub fn get_tx_bytes(&self) -> Result<u64, ErrorContext> {
686 let mut iter = self.clone();
687 iter.pos = 0;
688 for attr in iter {
689 if let Wgpeer::TxBytes(val) = attr? {
690 return Ok(val);
691 }
692 }
693 Err(ErrorContext::new_missing(
694 "Wgpeer",
695 "TxBytes",
696 self.orig_loc,
697 self.buf.as_ptr() as usize,
698 ))
699 }
700 #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
701 pub fn get_allowedips(
702 &self,
703 ) -> Result<ArrayIterable<IterableArrayWgallowedip<'a>, IterableWgallowedip<'a>>, ErrorContext>
704 {
705 for attr in self.clone() {
706 if let Wgpeer::Allowedips(val) = attr? {
707 return Ok(ArrayIterable::new(val));
708 }
709 }
710 Err(ErrorContext::new_missing(
711 "Wgpeer",
712 "Allowedips",
713 self.orig_loc,
714 self.buf.as_ptr() as usize,
715 ))
716 }
717 #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
718 pub fn get_protocol_version(&self) -> Result<u32, ErrorContext> {
719 let mut iter = self.clone();
720 iter.pos = 0;
721 for attr in iter {
722 if let Wgpeer::ProtocolVersion(val) = attr? {
723 return Ok(val);
724 }
725 }
726 Err(ErrorContext::new_missing(
727 "Wgpeer",
728 "ProtocolVersion",
729 self.orig_loc,
730 self.buf.as_ptr() as usize,
731 ))
732 }
733}
734impl Wgallowedip {
735 pub fn new_array(buf: &[u8]) -> IterableArrayWgallowedip<'_> {
736 IterableArrayWgallowedip::with_loc(buf, buf.as_ptr() as usize)
737 }
738}
739#[derive(Clone, Copy, Default)]
740pub struct IterableArrayWgallowedip<'a> {
741 buf: &'a [u8],
742 pos: usize,
743 orig_loc: usize,
744}
745impl<'a> IterableArrayWgallowedip<'a> {
746 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
747 Self {
748 buf,
749 pos: 0,
750 orig_loc,
751 }
752 }
753 pub fn get_buf(&self) -> &'a [u8] {
754 self.buf
755 }
756}
757impl<'a> Iterator for IterableArrayWgallowedip<'a> {
758 type Item = Result<IterableWgallowedip<'a>, ErrorContext>;
759 fn next(&mut self) -> Option<Self::Item> {
760 if self.buf.len() == self.pos {
761 return None;
762 }
763 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
764 {
765 return Some(Ok(IterableWgallowedip::with_loc(next, self.orig_loc)));
766 }
767 }
768 Some(Err(ErrorContext::new(
769 "Wgallowedip",
770 None,
771 self.orig_loc,
772 self.buf.as_ptr().wrapping_add(self.pos) as usize,
773 )))
774 }
775}
776impl Wgpeer<'_> {
777 pub fn new<'a>(buf: &'a [u8]) -> IterableWgpeer<'a> {
778 IterableWgpeer::with_loc(buf, buf.as_ptr() as usize)
779 }
780 fn attr_from_type(r#type: u16) -> Option<&'static str> {
781 let res = match r#type {
782 0u16 => "Unspec",
783 1u16 => "PublicKey",
784 2u16 => "PresharedKey",
785 3u16 => "Flags",
786 4u16 => "Endpoint",
787 5u16 => "PersistentKeepaliveInterval",
788 6u16 => "LastHandshakeTime",
789 7u16 => "RxBytes",
790 8u16 => "TxBytes",
791 9u16 => "Allowedips",
792 10u16 => "ProtocolVersion",
793 _ => return None,
794 };
795 Some(res)
796 }
797}
798#[derive(Clone, Copy, Default)]
799pub struct IterableWgpeer<'a> {
800 buf: &'a [u8],
801 pos: usize,
802 orig_loc: usize,
803}
804impl<'a> IterableWgpeer<'a> {
805 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
806 Self {
807 buf,
808 pos: 0,
809 orig_loc,
810 }
811 }
812 pub fn get_buf(&self) -> &'a [u8] {
813 self.buf
814 }
815}
816impl<'a> Iterator for IterableWgpeer<'a> {
817 type Item = Result<Wgpeer<'a>, ErrorContext>;
818 fn next(&mut self) -> Option<Self::Item> {
819 let pos = self.pos;
820 let mut r#type;
821 loop {
822 r#type = None;
823 if self.buf.len() == self.pos {
824 return None;
825 }
826 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
827 break;
828 };
829 r#type = Some(header.r#type);
830 let res = match header.r#type {
831 1u16 => Wgpeer::PublicKey({
832 let res = Some(next);
833 let Some(val) = res else { break };
834 val
835 }),
836 2u16 => Wgpeer::PresharedKey({
837 let res = Some(next);
838 let Some(val) = res else { break };
839 val
840 }),
841 3u16 => Wgpeer::Flags({
842 let res = parse_u32(next);
843 let Some(val) = res else { break };
844 val
845 }),
846 4u16 => Wgpeer::Endpoint({
847 let res = parse_sockaddr(next);
848 let Some(val) = res else { break };
849 val
850 }),
851 5u16 => Wgpeer::PersistentKeepaliveInterval({
852 let res = parse_u16(next);
853 let Some(val) = res else { break };
854 val
855 }),
856 6u16 => Wgpeer::LastHandshakeTime({
857 let res = Some(KernelTimespec::new_from_zeroed(next));
858 let Some(val) = res else { break };
859 val
860 }),
861 7u16 => Wgpeer::RxBytes({
862 let res = parse_u64(next);
863 let Some(val) = res else { break };
864 val
865 }),
866 8u16 => Wgpeer::TxBytes({
867 let res = parse_u64(next);
868 let Some(val) = res else { break };
869 val
870 }),
871 9u16 => Wgpeer::Allowedips({
872 let res = Some(IterableArrayWgallowedip::with_loc(next, self.orig_loc));
873 let Some(val) = res else { break };
874 val
875 }),
876 10u16 => Wgpeer::ProtocolVersion({
877 let res = parse_u32(next);
878 let Some(val) = res else { break };
879 val
880 }),
881 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
882 n => continue,
883 };
884 return Some(Ok(res));
885 }
886 Some(Err(ErrorContext::new(
887 "Wgpeer",
888 r#type.and_then(|t| Wgpeer::attr_from_type(t)),
889 self.orig_loc,
890 self.buf.as_ptr().wrapping_add(pos) as usize,
891 )))
892 }
893}
894impl std::fmt::Debug for IterableArrayWgallowedip<'_> {
895 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
896 fmt.debug_list()
897 .entries(self.clone().map(FlattenErrorContext))
898 .finish()
899 }
900}
901impl<'a> std::fmt::Debug for IterableWgpeer<'_> {
902 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
903 let mut fmt = f.debug_struct("Wgpeer");
904 for attr in self.clone() {
905 let attr = match attr {
906 Ok(a) => a,
907 Err(err) => {
908 fmt.finish()?;
909 f.write_str("Err(")?;
910 err.fmt(f)?;
911 return f.write_str(")");
912 }
913 };
914 match attr {
915 Wgpeer::PublicKey(val) => fmt.field("PublicKey", &FormatHex(val)),
916 Wgpeer::PresharedKey(val) => fmt.field("PresharedKey", &FormatHex(val)),
917 Wgpeer::Flags(val) => {
918 fmt.field("Flags", &FormatFlags(val.into(), WgpeerFlags::from_value))
919 }
920 Wgpeer::Endpoint(val) => fmt.field("Endpoint", &val),
921 Wgpeer::PersistentKeepaliveInterval(val) => {
922 fmt.field("PersistentKeepaliveInterval", &val)
923 }
924 Wgpeer::LastHandshakeTime(val) => fmt.field("LastHandshakeTime", &val),
925 Wgpeer::RxBytes(val) => fmt.field("RxBytes", &val),
926 Wgpeer::TxBytes(val) => fmt.field("TxBytes", &val),
927 Wgpeer::Allowedips(val) => fmt.field("Allowedips", &val),
928 Wgpeer::ProtocolVersion(val) => fmt.field("ProtocolVersion", &val),
929 };
930 }
931 fmt.finish()
932 }
933}
934impl IterableWgpeer<'_> {
935 pub fn lookup_attr(
936 &self,
937 offset: usize,
938 missing_type: Option<u16>,
939 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
940 let mut stack = Vec::new();
941 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
942 if missing_type.is_some() && cur == offset {
943 stack.push(("Wgpeer", offset));
944 return (stack, missing_type.and_then(|t| Wgpeer::attr_from_type(t)));
945 }
946 if cur > offset || cur + self.buf.len() < offset {
947 return (stack, None);
948 }
949 let mut attrs = self.clone();
950 let mut last_off = cur + attrs.pos;
951 let mut missing = None;
952 while let Some(attr) = attrs.next() {
953 let Ok(attr) = attr else { break };
954 match attr {
955 Wgpeer::PublicKey(val) => {
956 if last_off == offset {
957 stack.push(("PublicKey", last_off));
958 break;
959 }
960 }
961 Wgpeer::PresharedKey(val) => {
962 if last_off == offset {
963 stack.push(("PresharedKey", last_off));
964 break;
965 }
966 }
967 Wgpeer::Flags(val) => {
968 if last_off == offset {
969 stack.push(("Flags", last_off));
970 break;
971 }
972 }
973 Wgpeer::Endpoint(val) => {
974 if last_off == offset {
975 stack.push(("Endpoint", last_off));
976 break;
977 }
978 }
979 Wgpeer::PersistentKeepaliveInterval(val) => {
980 if last_off == offset {
981 stack.push(("PersistentKeepaliveInterval", last_off));
982 break;
983 }
984 }
985 Wgpeer::LastHandshakeTime(val) => {
986 if last_off == offset {
987 stack.push(("LastHandshakeTime", last_off));
988 break;
989 }
990 }
991 Wgpeer::RxBytes(val) => {
992 if last_off == offset {
993 stack.push(("RxBytes", last_off));
994 break;
995 }
996 }
997 Wgpeer::TxBytes(val) => {
998 if last_off == offset {
999 stack.push(("TxBytes", last_off));
1000 break;
1001 }
1002 }
1003 Wgpeer::Allowedips(val) => {
1004 for entry in val {
1005 let Ok(attr) = entry else { break };
1006 (stack, missing) = attr.lookup_attr(offset, missing_type);
1007 if !stack.is_empty() {
1008 break;
1009 }
1010 }
1011 if !stack.is_empty() {
1012 stack.push(("Allowedips", last_off));
1013 break;
1014 }
1015 }
1016 Wgpeer::ProtocolVersion(val) => {
1017 if last_off == offset {
1018 stack.push(("ProtocolVersion", last_off));
1019 break;
1020 }
1021 }
1022 _ => {}
1023 };
1024 last_off = cur + attrs.pos;
1025 }
1026 if !stack.is_empty() {
1027 stack.push(("Wgpeer", cur));
1028 }
1029 (stack, missing)
1030 }
1031}
1032#[derive(Clone)]
1033pub enum Wgallowedip {
1034 #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1035 Family(u16),
1036 #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1037 Ipaddr(std::net::IpAddr),
1038 CidrMask(u8),
1039 #[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)"]
1040 Flags(u32),
1041}
1042impl<'a> IterableWgallowedip<'a> {
1043 #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1044 pub fn get_family(&self) -> Result<u16, ErrorContext> {
1045 let mut iter = self.clone();
1046 iter.pos = 0;
1047 for attr in iter {
1048 if let Wgallowedip::Family(val) = attr? {
1049 return Ok(val);
1050 }
1051 }
1052 Err(ErrorContext::new_missing(
1053 "Wgallowedip",
1054 "Family",
1055 self.orig_loc,
1056 self.buf.as_ptr() as usize,
1057 ))
1058 }
1059 #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1060 pub fn get_ipaddr(&self) -> Result<std::net::IpAddr, ErrorContext> {
1061 let mut iter = self.clone();
1062 iter.pos = 0;
1063 for attr in iter {
1064 if let Wgallowedip::Ipaddr(val) = attr? {
1065 return Ok(val);
1066 }
1067 }
1068 Err(ErrorContext::new_missing(
1069 "Wgallowedip",
1070 "Ipaddr",
1071 self.orig_loc,
1072 self.buf.as_ptr() as usize,
1073 ))
1074 }
1075 pub fn get_cidr_mask(&self) -> Result<u8, ErrorContext> {
1076 let mut iter = self.clone();
1077 iter.pos = 0;
1078 for attr in iter {
1079 if let Wgallowedip::CidrMask(val) = attr? {
1080 return Ok(val);
1081 }
1082 }
1083 Err(ErrorContext::new_missing(
1084 "Wgallowedip",
1085 "CidrMask",
1086 self.orig_loc,
1087 self.buf.as_ptr() as usize,
1088 ))
1089 }
1090 #[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)"]
1091 pub fn get_flags(&self) -> Result<u32, ErrorContext> {
1092 let mut iter = self.clone();
1093 iter.pos = 0;
1094 for attr in iter {
1095 if let Wgallowedip::Flags(val) = attr? {
1096 return Ok(val);
1097 }
1098 }
1099 Err(ErrorContext::new_missing(
1100 "Wgallowedip",
1101 "Flags",
1102 self.orig_loc,
1103 self.buf.as_ptr() as usize,
1104 ))
1105 }
1106}
1107impl Wgallowedip {
1108 pub fn new<'a>(buf: &'a [u8]) -> IterableWgallowedip<'a> {
1109 IterableWgallowedip::with_loc(buf, buf.as_ptr() as usize)
1110 }
1111 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1112 let res = match r#type {
1113 0u16 => "Unspec",
1114 1u16 => "Family",
1115 2u16 => "Ipaddr",
1116 3u16 => "CidrMask",
1117 4u16 => "Flags",
1118 _ => return None,
1119 };
1120 Some(res)
1121 }
1122}
1123#[derive(Clone, Copy, Default)]
1124pub struct IterableWgallowedip<'a> {
1125 buf: &'a [u8],
1126 pos: usize,
1127 orig_loc: usize,
1128}
1129impl<'a> IterableWgallowedip<'a> {
1130 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1131 Self {
1132 buf,
1133 pos: 0,
1134 orig_loc,
1135 }
1136 }
1137 pub fn get_buf(&self) -> &'a [u8] {
1138 self.buf
1139 }
1140}
1141impl<'a> Iterator for IterableWgallowedip<'a> {
1142 type Item = Result<Wgallowedip, ErrorContext>;
1143 fn next(&mut self) -> Option<Self::Item> {
1144 let pos = self.pos;
1145 let mut r#type;
1146 loop {
1147 r#type = None;
1148 if self.buf.len() == self.pos {
1149 return None;
1150 }
1151 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1152 break;
1153 };
1154 r#type = Some(header.r#type);
1155 let res = match header.r#type {
1156 1u16 => Wgallowedip::Family({
1157 let res = parse_u16(next);
1158 let Some(val) = res else { break };
1159 val
1160 }),
1161 2u16 => Wgallowedip::Ipaddr({
1162 let res = parse_ip(next);
1163 let Some(val) = res else { break };
1164 val
1165 }),
1166 3u16 => Wgallowedip::CidrMask({
1167 let res = parse_u8(next);
1168 let Some(val) = res else { break };
1169 val
1170 }),
1171 4u16 => Wgallowedip::Flags({
1172 let res = parse_u32(next);
1173 let Some(val) = res else { break };
1174 val
1175 }),
1176 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1177 n => continue,
1178 };
1179 return Some(Ok(res));
1180 }
1181 Some(Err(ErrorContext::new(
1182 "Wgallowedip",
1183 r#type.and_then(|t| Wgallowedip::attr_from_type(t)),
1184 self.orig_loc,
1185 self.buf.as_ptr().wrapping_add(pos) as usize,
1186 )))
1187 }
1188}
1189impl std::fmt::Debug for IterableWgallowedip<'_> {
1190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1191 let mut fmt = f.debug_struct("Wgallowedip");
1192 for attr in self.clone() {
1193 let attr = match attr {
1194 Ok(a) => a,
1195 Err(err) => {
1196 fmt.finish()?;
1197 f.write_str("Err(")?;
1198 err.fmt(f)?;
1199 return f.write_str(")");
1200 }
1201 };
1202 match attr {
1203 Wgallowedip::Family(val) => fmt.field("Family", &val),
1204 Wgallowedip::Ipaddr(val) => fmt.field("Ipaddr", &val),
1205 Wgallowedip::CidrMask(val) => fmt.field("CidrMask", &val),
1206 Wgallowedip::Flags(val) => fmt.field(
1207 "Flags",
1208 &FormatFlags(val.into(), WgallowedipFlags::from_value),
1209 ),
1210 };
1211 }
1212 fmt.finish()
1213 }
1214}
1215impl IterableWgallowedip<'_> {
1216 pub fn lookup_attr(
1217 &self,
1218 offset: usize,
1219 missing_type: Option<u16>,
1220 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1221 let mut stack = Vec::new();
1222 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1223 if missing_type.is_some() && cur == offset {
1224 stack.push(("Wgallowedip", offset));
1225 return (
1226 stack,
1227 missing_type.and_then(|t| Wgallowedip::attr_from_type(t)),
1228 );
1229 }
1230 if cur > offset || cur + self.buf.len() < offset {
1231 return (stack, None);
1232 }
1233 let mut attrs = self.clone();
1234 let mut last_off = cur + attrs.pos;
1235 while let Some(attr) = attrs.next() {
1236 let Ok(attr) = attr else { break };
1237 match attr {
1238 Wgallowedip::Family(val) => {
1239 if last_off == offset {
1240 stack.push(("Family", last_off));
1241 break;
1242 }
1243 }
1244 Wgallowedip::Ipaddr(val) => {
1245 if last_off == offset {
1246 stack.push(("Ipaddr", last_off));
1247 break;
1248 }
1249 }
1250 Wgallowedip::CidrMask(val) => {
1251 if last_off == offset {
1252 stack.push(("CidrMask", last_off));
1253 break;
1254 }
1255 }
1256 Wgallowedip::Flags(val) => {
1257 if last_off == offset {
1258 stack.push(("Flags", last_off));
1259 break;
1260 }
1261 }
1262 _ => {}
1263 };
1264 last_off = cur + attrs.pos;
1265 }
1266 if !stack.is_empty() {
1267 stack.push(("Wgallowedip", cur));
1268 }
1269 (stack, None)
1270 }
1271}
1272pub struct PushWgdevice<Prev: Rec> {
1273 pub(crate) prev: Option<Prev>,
1274 pub(crate) header_offset: Option<usize>,
1275}
1276impl<Prev: Rec> Rec for PushWgdevice<Prev> {
1277 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1278 self.prev.as_mut().unwrap().as_rec_mut()
1279 }
1280 fn as_rec(&self) -> &Vec<u8> {
1281 self.prev.as_ref().unwrap().as_rec()
1282 }
1283}
1284pub struct PushArrayWgpeer<Prev: Rec> {
1285 pub(crate) prev: Option<Prev>,
1286 pub(crate) header_offset: Option<usize>,
1287 pub(crate) counter: u16,
1288}
1289impl<Prev: Rec> Rec for PushArrayWgpeer<Prev> {
1290 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1291 self.prev.as_mut().unwrap().as_rec_mut()
1292 }
1293 fn as_rec(&self) -> &Vec<u8> {
1294 self.prev.as_ref().unwrap().as_rec()
1295 }
1296}
1297impl<Prev: Rec> PushArrayWgpeer<Prev> {
1298 pub fn new(prev: Prev) -> Self {
1299 Self {
1300 prev: Some(prev),
1301 header_offset: None,
1302 counter: 0,
1303 }
1304 }
1305 pub fn end_array(mut self) -> Prev {
1306 let mut prev = self.prev.take().unwrap();
1307 if let Some(header_offset) = &self.header_offset {
1308 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1309 }
1310 prev
1311 }
1312 pub fn entry_nested(mut self) -> PushWgpeer<Self> {
1313 let index = self.counter;
1314 self.counter += 1;
1315 let header_offset = push_nested_header(self.as_rec_mut(), index);
1316 PushWgpeer {
1317 prev: Some(self),
1318 header_offset: Some(header_offset),
1319 }
1320 }
1321}
1322impl<Prev: Rec> Drop for PushArrayWgpeer<Prev> {
1323 fn drop(&mut self) {
1324 if let Some(prev) = &mut self.prev {
1325 if let Some(header_offset) = &self.header_offset {
1326 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1327 }
1328 }
1329 }
1330}
1331impl<Prev: Rec> PushWgdevice<Prev> {
1332 pub fn new(prev: Prev) -> Self {
1333 Self {
1334 prev: Some(prev),
1335 header_offset: None,
1336 }
1337 }
1338 pub fn end_nested(mut self) -> Prev {
1339 let mut prev = self.prev.take().unwrap();
1340 if let Some(header_offset) = &self.header_offset {
1341 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1342 }
1343 prev
1344 }
1345 pub fn push_ifindex(mut self, value: u32) -> Self {
1346 push_header(self.as_rec_mut(), 1u16, 4 as u16);
1347 self.as_rec_mut().extend(value.to_ne_bytes());
1348 self
1349 }
1350 pub fn push_ifname(mut self, value: &CStr) -> Self {
1351 push_header(
1352 self.as_rec_mut(),
1353 2u16,
1354 value.to_bytes_with_nul().len() as u16,
1355 );
1356 self.as_rec_mut().extend(value.to_bytes_with_nul());
1357 self
1358 }
1359 pub fn push_ifname_bytes(mut self, value: &[u8]) -> Self {
1360 push_header(self.as_rec_mut(), 2u16, (value.len() + 1) as u16);
1361 self.as_rec_mut().extend(value);
1362 self.as_rec_mut().push(0);
1363 self
1364 }
1365 #[doc = "Set to all zeros to remove\\."]
1366 pub fn push_private_key(mut self, value: &[u8]) -> Self {
1367 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
1368 self.as_rec_mut().extend(value);
1369 self
1370 }
1371 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1372 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1373 self.as_rec_mut().extend(value);
1374 self
1375 }
1376 #[doc = "\\`\\`0\\`\\` or \\`\\`WGDEVICE\\_F\\_REPLACE\\_PEERS\\`\\` if all current peers should be\nremoved prior to adding the list below\\.\n\nAssociated type: [`WgdeviceFlags`] (enum)"]
1377 pub fn push_flags(mut self, value: u32) -> Self {
1378 push_header(self.as_rec_mut(), 5u16, 4 as u16);
1379 self.as_rec_mut().extend(value.to_ne_bytes());
1380 self
1381 }
1382 #[doc = "Set as \\`\\`0\\`\\` to choose randomly\\."]
1383 pub fn push_listen_port(mut self, value: u16) -> Self {
1384 push_header(self.as_rec_mut(), 6u16, 2 as u16);
1385 self.as_rec_mut().extend(value.to_ne_bytes());
1386 self
1387 }
1388 #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
1389 pub fn push_fwmark(mut self, value: u32) -> Self {
1390 push_header(self.as_rec_mut(), 7u16, 4 as u16);
1391 self.as_rec_mut().extend(value.to_ne_bytes());
1392 self
1393 }
1394 #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
1395 pub fn array_peers(mut self) -> PushArrayWgpeer<Self> {
1396 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
1397 PushArrayWgpeer {
1398 prev: Some(self),
1399 header_offset: Some(header_offset),
1400 counter: 0,
1401 }
1402 }
1403}
1404impl<Prev: Rec> Drop for PushWgdevice<Prev> {
1405 fn drop(&mut self) {
1406 if let Some(prev) = &mut self.prev {
1407 if let Some(header_offset) = &self.header_offset {
1408 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1409 }
1410 }
1411 }
1412}
1413pub struct PushWgpeer<Prev: Rec> {
1414 pub(crate) prev: Option<Prev>,
1415 pub(crate) header_offset: Option<usize>,
1416}
1417impl<Prev: Rec> Rec for PushWgpeer<Prev> {
1418 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1419 self.prev.as_mut().unwrap().as_rec_mut()
1420 }
1421 fn as_rec(&self) -> &Vec<u8> {
1422 self.prev.as_ref().unwrap().as_rec()
1423 }
1424}
1425pub struct PushArrayWgallowedip<Prev: Rec> {
1426 pub(crate) prev: Option<Prev>,
1427 pub(crate) header_offset: Option<usize>,
1428 pub(crate) counter: u16,
1429}
1430impl<Prev: Rec> Rec for PushArrayWgallowedip<Prev> {
1431 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1432 self.prev.as_mut().unwrap().as_rec_mut()
1433 }
1434 fn as_rec(&self) -> &Vec<u8> {
1435 self.prev.as_ref().unwrap().as_rec()
1436 }
1437}
1438impl<Prev: Rec> PushArrayWgallowedip<Prev> {
1439 pub fn new(prev: Prev) -> Self {
1440 Self {
1441 prev: Some(prev),
1442 header_offset: None,
1443 counter: 0,
1444 }
1445 }
1446 pub fn end_array(mut self) -> Prev {
1447 let mut prev = self.prev.take().unwrap();
1448 if let Some(header_offset) = &self.header_offset {
1449 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1450 }
1451 prev
1452 }
1453 pub fn entry_nested(mut self) -> PushWgallowedip<Self> {
1454 let index = self.counter;
1455 self.counter += 1;
1456 let header_offset = push_nested_header(self.as_rec_mut(), index);
1457 PushWgallowedip {
1458 prev: Some(self),
1459 header_offset: Some(header_offset),
1460 }
1461 }
1462}
1463impl<Prev: Rec> Drop for PushArrayWgallowedip<Prev> {
1464 fn drop(&mut self) {
1465 if let Some(prev) = &mut self.prev {
1466 if let Some(header_offset) = &self.header_offset {
1467 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1468 }
1469 }
1470 }
1471}
1472impl<Prev: Rec> PushWgpeer<Prev> {
1473 pub fn new(prev: Prev) -> Self {
1474 Self {
1475 prev: Some(prev),
1476 header_offset: None,
1477 }
1478 }
1479 pub fn end_nested(mut self) -> Prev {
1480 let mut prev = self.prev.take().unwrap();
1481 if let Some(header_offset) = &self.header_offset {
1482 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1483 }
1484 prev
1485 }
1486 pub fn push_public_key(mut self, value: &[u8]) -> Self {
1487 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
1488 self.as_rec_mut().extend(value);
1489 self
1490 }
1491 #[doc = "Set as all zeros to remove\\."]
1492 pub fn push_preshared_key(mut self, value: &[u8]) -> Self {
1493 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
1494 self.as_rec_mut().extend(value);
1495 self
1496 }
1497 #[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 and/or\n\\`\\`WGPEER\\_F\\_REPLACE\\_ALLOWEDIPS\\`\\` if all current allowed IPs of this\npeer should 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)"]
1498 pub fn push_flags(mut self, value: u32) -> Self {
1499 push_header(self.as_rec_mut(), 3u16, 4 as u16);
1500 self.as_rec_mut().extend(value.to_ne_bytes());
1501 self
1502 }
1503 #[doc = "struct sockaddr\\_in or struct sockaddr\\_in6"]
1504 pub fn push_endpoint(mut self, value: std::net::SocketAddr) -> Self {
1505 push_header(self.as_rec_mut(), 4u16, {
1506 match &value {
1507 SocketAddr::V4(_) => 16,
1508 SocketAddr::V6(_) => 28,
1509 }
1510 } as u16);
1511 encode_sockaddr(self.as_rec_mut(), value);
1512 self
1513 }
1514 #[doc = "Set as \\`\\`0\\`\\` to disable\\."]
1515 pub fn push_persistent_keepalive_interval(mut self, value: u16) -> Self {
1516 push_header(self.as_rec_mut(), 5u16, 2 as u16);
1517 self.as_rec_mut().extend(value.to_ne_bytes());
1518 self
1519 }
1520 pub fn push_last_handshake_time(mut self, value: KernelTimespec) -> Self {
1521 push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
1522 self.as_rec_mut().extend(value.as_slice());
1523 self
1524 }
1525 pub fn push_rx_bytes(mut self, value: u64) -> Self {
1526 push_header(self.as_rec_mut(), 7u16, 8 as u16);
1527 self.as_rec_mut().extend(value.to_ne_bytes());
1528 self
1529 }
1530 pub fn push_tx_bytes(mut self, value: u64) -> Self {
1531 push_header(self.as_rec_mut(), 8u16, 8 as u16);
1532 self.as_rec_mut().extend(value.to_ne_bytes());
1533 self
1534 }
1535 #[doc = "The index/type parameter is unused on \\`\\`SET\\_DEVICE\\`\\` operations and is\nzero on \\`\\`GET\\_DEVICE\\`\\` operations\\.\n"]
1536 pub fn array_allowedips(mut self) -> PushArrayWgallowedip<Self> {
1537 let header_offset = push_nested_header(self.as_rec_mut(), 9u16);
1538 PushArrayWgallowedip {
1539 prev: Some(self),
1540 header_offset: Some(header_offset),
1541 counter: 0,
1542 }
1543 }
1544 #[doc = "Should not be set or used at all by most users of this API, as the\nmost recent protocol will be used when this is unset\\. Otherwise,\nmust be set to \\`\\`1\\`\\`\\.\n"]
1545 pub fn push_protocol_version(mut self, value: u32) -> Self {
1546 push_header(self.as_rec_mut(), 10u16, 4 as u16);
1547 self.as_rec_mut().extend(value.to_ne_bytes());
1548 self
1549 }
1550}
1551impl<Prev: Rec> Drop for PushWgpeer<Prev> {
1552 fn drop(&mut self) {
1553 if let Some(prev) = &mut self.prev {
1554 if let Some(header_offset) = &self.header_offset {
1555 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1556 }
1557 }
1558 }
1559}
1560pub struct PushWgallowedip<Prev: Rec> {
1561 pub(crate) prev: Option<Prev>,
1562 pub(crate) header_offset: Option<usize>,
1563}
1564impl<Prev: Rec> Rec for PushWgallowedip<Prev> {
1565 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1566 self.prev.as_mut().unwrap().as_rec_mut()
1567 }
1568 fn as_rec(&self) -> &Vec<u8> {
1569 self.prev.as_ref().unwrap().as_rec()
1570 }
1571}
1572impl<Prev: Rec> PushWgallowedip<Prev> {
1573 pub fn new(prev: Prev) -> Self {
1574 Self {
1575 prev: Some(prev),
1576 header_offset: None,
1577 }
1578 }
1579 pub fn end_nested(mut self) -> Prev {
1580 let mut prev = self.prev.take().unwrap();
1581 if let Some(header_offset) = &self.header_offset {
1582 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1583 }
1584 prev
1585 }
1586 #[doc = "IP family, either \\`\\`AF\\_INET\\`\\` or \\`\\`AF\\_INET6\\`\\`\\."]
1587 pub fn push_family(mut self, value: u16) -> Self {
1588 push_header(self.as_rec_mut(), 1u16, 2 as u16);
1589 self.as_rec_mut().extend(value.to_ne_bytes());
1590 self
1591 }
1592 #[doc = "Either \\`\\`struct in\\_addr\\`\\` or \\`\\`struct in6\\_addr\\`\\`\\."]
1593 pub fn push_ipaddr(mut self, value: std::net::IpAddr) -> Self {
1594 push_header(self.as_rec_mut(), 2u16, {
1595 match &value {
1596 IpAddr::V4(_) => 4,
1597 IpAddr::V6(_) => 16,
1598 }
1599 } as u16);
1600 encode_ip(self.as_rec_mut(), value);
1601 self
1602 }
1603 pub fn push_cidr_mask(mut self, value: u8) -> Self {
1604 push_header(self.as_rec_mut(), 3u16, 1 as u16);
1605 self.as_rec_mut().extend(value.to_ne_bytes());
1606 self
1607 }
1608 #[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)"]
1609 pub fn push_flags(mut self, value: u32) -> Self {
1610 push_header(self.as_rec_mut(), 4u16, 4 as u16);
1611 self.as_rec_mut().extend(value.to_ne_bytes());
1612 self
1613 }
1614}
1615impl<Prev: Rec> Drop for PushWgallowedip<Prev> {
1616 fn drop(&mut self) {
1617 if let Some(prev) = &mut self.prev {
1618 if let Some(header_offset) = &self.header_offset {
1619 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1620 }
1621 }
1622 }
1623}
1624#[doc = "Retrieve WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\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\nseveral times in a row for the same peer\\. It is then up to the receiver\nto coalesce 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\nthese messages to form the complete list of peers\\.\n\nSince this is an \\`\\`NLA\\_F\\_DUMP\\`\\` command, the final message will always\nbe \\`\\`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\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"]
1625#[derive(Debug)]
1626pub struct OpGetDeviceDump<'r> {
1627 request: Request<'r>,
1628}
1629impl<'r> OpGetDeviceDump<'r> {
1630 pub fn new(mut request: Request<'r>) -> Self {
1631 Self::write_header(request.buf_mut());
1632 Self {
1633 request: request.set_dump(),
1634 }
1635 }
1636 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1637 Self::write_header(buf);
1638 PushWgdevice::new(buf)
1639 }
1640 pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1641 PushWgdevice::new(self.request.buf_mut())
1642 }
1643 pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1644 PushWgdevice::new(self.request.buf)
1645 }
1646 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1647 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1648 IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1649 }
1650 fn write_header<Prev: Rec>(prev: &mut Prev) {
1651 let mut header = BuiltinNfgenmsg::new();
1652 header.cmd = 0u8;
1653 header.version = 1u8;
1654 prev.as_rec_mut().extend(header.as_slice());
1655 }
1656}
1657impl NetlinkRequest for OpGetDeviceDump<'_> {
1658 fn protocol(&self) -> Protocol {
1659 Protocol::Generic("wireguard".as_bytes())
1660 }
1661 fn flags(&self) -> u16 {
1662 self.request.flags
1663 }
1664 fn payload(&self) -> &[u8] {
1665 self.request.buf()
1666 }
1667 type ReplyType<'buf> = IterableWgdevice<'buf>;
1668 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1669 Self::decode_request(buf)
1670 }
1671 fn lookup(
1672 buf: &[u8],
1673 offset: usize,
1674 missing_type: Option<u16>,
1675 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1676 Self::decode_request(buf).lookup_attr(offset, missing_type)
1677 }
1678}
1679#[doc = "Set WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\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\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\nFlags: uns-admin-perm\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"]
1680#[derive(Debug)]
1681pub struct OpSetDeviceDo<'r> {
1682 request: Request<'r>,
1683}
1684impl<'r> OpSetDeviceDo<'r> {
1685 pub fn new(mut request: Request<'r>) -> Self {
1686 Self::write_header(request.buf_mut());
1687 Self { request: request }
1688 }
1689 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushWgdevice<&'buf mut Vec<u8>> {
1690 Self::write_header(buf);
1691 PushWgdevice::new(buf)
1692 }
1693 pub fn encode(&mut self) -> PushWgdevice<&mut Vec<u8>> {
1694 PushWgdevice::new(self.request.buf_mut())
1695 }
1696 pub fn into_encoder(self) -> PushWgdevice<RequestBuf<'r>> {
1697 PushWgdevice::new(self.request.buf)
1698 }
1699 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableWgdevice<'a> {
1700 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1701 IterableWgdevice::with_loc(attrs, buf.as_ptr() as usize)
1702 }
1703 fn write_header<Prev: Rec>(prev: &mut Prev) {
1704 let mut header = BuiltinNfgenmsg::new();
1705 header.cmd = 1u8;
1706 header.version = 1u8;
1707 prev.as_rec_mut().extend(header.as_slice());
1708 }
1709}
1710impl NetlinkRequest for OpSetDeviceDo<'_> {
1711 fn protocol(&self) -> Protocol {
1712 Protocol::Generic("wireguard".as_bytes())
1713 }
1714 fn flags(&self) -> u16 {
1715 self.request.flags
1716 }
1717 fn payload(&self) -> &[u8] {
1718 self.request.buf()
1719 }
1720 type ReplyType<'buf> = IterableWgdevice<'buf>;
1721 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1722 Self::decode_request(buf)
1723 }
1724 fn lookup(
1725 buf: &[u8],
1726 offset: usize,
1727 missing_type: Option<u16>,
1728 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1729 Self::decode_request(buf).lookup_attr(offset, missing_type)
1730 }
1731}
1732use crate::traits::LookupFn;
1733use crate::utils::RequestBuf;
1734#[derive(Debug)]
1735pub struct Request<'buf> {
1736 buf: RequestBuf<'buf>,
1737 flags: u16,
1738 writeback: Option<&'buf mut Option<RequestInfo>>,
1739}
1740#[allow(unused)]
1741#[derive(Debug, Clone)]
1742pub struct RequestInfo {
1743 protocol: Protocol,
1744 flags: u16,
1745 name: &'static str,
1746 lookup: LookupFn,
1747}
1748impl Request<'static> {
1749 pub fn new() -> Self {
1750 Self::new_from_buf(Vec::new())
1751 }
1752 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1753 Self {
1754 flags: 0,
1755 buf: RequestBuf::Own(buf),
1756 writeback: None,
1757 }
1758 }
1759 pub fn into_buf(self) -> Vec<u8> {
1760 match self.buf {
1761 RequestBuf::Own(buf) => buf,
1762 _ => unreachable!(),
1763 }
1764 }
1765}
1766impl<'buf> Request<'buf> {
1767 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1768 buf.clear();
1769 Self::new_extend(buf)
1770 }
1771 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1772 Self {
1773 flags: 0,
1774 buf: RequestBuf::Ref(buf),
1775 writeback: None,
1776 }
1777 }
1778 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1779 let Some(writeback) = &mut self.writeback else {
1780 return;
1781 };
1782 **writeback = Some(RequestInfo {
1783 protocol,
1784 flags: self.flags,
1785 name,
1786 lookup,
1787 })
1788 }
1789 pub fn buf(&self) -> &Vec<u8> {
1790 self.buf.buf()
1791 }
1792 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1793 self.buf.buf_mut()
1794 }
1795 #[doc = "Set `NLM_F_CREATE` flag"]
1796 pub fn set_create(mut self) -> Self {
1797 self.flags |= consts::NLM_F_CREATE as u16;
1798 self
1799 }
1800 #[doc = "Set `NLM_F_EXCL` flag"]
1801 pub fn set_excl(mut self) -> Self {
1802 self.flags |= consts::NLM_F_EXCL as u16;
1803 self
1804 }
1805 #[doc = "Set `NLM_F_REPLACE` flag"]
1806 pub fn set_replace(mut self) -> Self {
1807 self.flags |= consts::NLM_F_REPLACE as u16;
1808 self
1809 }
1810 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1811 pub fn set_change(self) -> Self {
1812 self.set_create().set_replace()
1813 }
1814 #[doc = "Set `NLM_F_APPEND` flag"]
1815 pub fn set_append(mut self) -> Self {
1816 self.flags |= consts::NLM_F_APPEND as u16;
1817 self
1818 }
1819 #[doc = "Set `self.flags |= flags`"]
1820 pub fn set_flags(mut self, flags: u16) -> Self {
1821 self.flags |= flags;
1822 self
1823 }
1824 #[doc = "Set `self.flags ^= self.flags & flags`"]
1825 pub fn unset_flags(mut self, flags: u16) -> Self {
1826 self.flags ^= self.flags & flags;
1827 self
1828 }
1829 #[doc = "Set `NLM_F_DUMP` flag"]
1830 fn set_dump(mut self) -> Self {
1831 self.flags |= consts::NLM_F_DUMP as u16;
1832 self
1833 }
1834 #[doc = "Retrieve WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\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\nseveral times in a row for the same peer\\. It is then up to the receiver\nto coalesce 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\nthese messages to form the complete list of peers\\.\n\nSince this is an \\`\\`NLA\\_F\\_DUMP\\`\\` command, the final message will always\nbe \\`\\`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\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"]
1835 pub fn op_get_device_dump(self) -> OpGetDeviceDump<'buf> {
1836 let mut res = OpGetDeviceDump::new(self);
1837 res.request.do_writeback(
1838 res.protocol(),
1839 "op-get-device-dump",
1840 OpGetDeviceDump::lookup,
1841 );
1842 res
1843 }
1844 #[doc = "Set WireGuard device\n\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\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\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\nFlags: uns-admin-perm\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"]
1845 pub fn op_set_device_do(self) -> OpSetDeviceDo<'buf> {
1846 let mut res = OpSetDeviceDo::new(self);
1847 res.request
1848 .do_writeback(res.protocol(), "op-set-device-do", OpSetDeviceDo::lookup);
1849 res
1850 }
1851}
1852#[cfg(test)]
1853mod generated_tests {
1854 use super::*;
1855 #[test]
1856 fn tests() {
1857 let _ = IterableWgdevice::get_flags;
1858 let _ = IterableWgdevice::get_fwmark;
1859 let _ = IterableWgdevice::get_ifindex;
1860 let _ = IterableWgdevice::get_ifname;
1861 let _ = IterableWgdevice::get_listen_port;
1862 let _ = IterableWgdevice::get_peers;
1863 let _ = IterableWgdevice::get_private_key;
1864 let _ = IterableWgdevice::get_public_key;
1865 let _ = PushWgdevice::<&mut Vec<u8>>::array_peers;
1866 let _ = PushWgdevice::<&mut Vec<u8>>::push_flags;
1867 let _ = PushWgdevice::<&mut Vec<u8>>::push_fwmark;
1868 let _ = PushWgdevice::<&mut Vec<u8>>::push_ifindex;
1869 let _ = PushWgdevice::<&mut Vec<u8>>::push_ifname;
1870 let _ = PushWgdevice::<&mut Vec<u8>>::push_listen_port;
1871 let _ = PushWgdevice::<&mut Vec<u8>>::push_private_key;
1872 let _ = PushWgdevice::<&mut Vec<u8>>::push_public_key;
1873 }
1874}