summaryrefslogtreecommitdiff
path: root/src/view.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/view.rs')
-rw-r--r--src/view.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/view.rs b/src/view.rs
new file mode 100644
index 0000000..2858811
--- /dev/null
+++ b/src/view.rs
@@ -0,0 +1,130 @@
1use std::{net::SocketAddr, time::SystemTime};
2
3use ipnet::IpNet;
4use netlink_packet_wireguard::{
5 nlas::{WgAllowedIp, WgAllowedIpAttrs, WgDeviceAttrs, WgPeer, WgPeerAttrs},
6 Wireguard,
7};
8
9use super::{Error, Key, Result};
10
11#[derive(Debug, Clone)]
12pub struct DeviceView {
13 pub name: String,
14 pub ifindex: u32,
15 pub private_key: Option<Key>,
16 pub public_key: Option<Key>,
17 pub listen_port: u16,
18 pub fwmark: u32,
19 pub peers: Vec<PeerView>,
20}
21
22#[derive(Debug, Clone)]
23pub struct PeerView {
24 pub public_key: Key,
25 pub preshared_key: Option<Key>,
26 pub endpoint: Option<SocketAddr>,
27 pub persistent_keepalive: Option<u16>,
28 pub last_handshake: SystemTime,
29 pub rx_bytes: u64,
30 pub tx_bytes: u64,
31 pub allowed_ips: Vec<IpNet>,
32}
33
34pub(super) fn device_view_from_payload(wg: Wireguard) -> Result<DeviceView> {
35 let mut if_index = None;
36 let mut if_name = None;
37 let mut private_key = None;
38 let mut public_key = None;
39 let mut listen_port = None;
40 let mut fwmark = None;
41 let mut peers = None;
42
43 for nla in wg.nlas {
44 match nla {
45 WgDeviceAttrs::IfIndex(v) => if_index = Some(v),
46 WgDeviceAttrs::IfName(v) => if_name = Some(v),
47 WgDeviceAttrs::PrivateKey(v) => private_key = Some(Key::from(v)),
48 WgDeviceAttrs::PublicKey(v) => public_key = Some(Key::from(v)),
49 WgDeviceAttrs::ListenPort(v) => listen_port = Some(v),
50 WgDeviceAttrs::Fwmark(v) => fwmark = Some(v),
51 WgDeviceAttrs::Peers(v) => peers = Some(peers_from_wg_peers(v)?),
52 _ => {}
53 }
54 }
55
56 Ok(DeviceView {
57 name: if_name.ok_or_else(|| Error::message("missing if_name"))?,
58 ifindex: if_index.ok_or_else(|| Error::message("missing if_index"))?,
59 private_key,
60 public_key,
61 listen_port: listen_port.ok_or_else(|| Error::message("missing listen_port"))?,
62 fwmark: fwmark.ok_or_else(|| Error::message("missing fwmark"))?,
63 peers: peers.unwrap_or_default(),
64 })
65}
66
67fn peers_from_wg_peers(wg_peers: Vec<WgPeer>) -> Result<Vec<PeerView>> {
68 let mut peers = Vec::with_capacity(wg_peers.len());
69 for wg_peer in wg_peers {
70 peers.push(peer_from_wg_peer(wg_peer)?);
71 }
72 Ok(peers)
73}
74
75fn peer_from_wg_peer(wg_peer: WgPeer) -> Result<PeerView> {
76 let mut public_key = None;
77 let mut preshared_key = None;
78 let mut endpoint = None;
79 let mut persistent_keepalive = None;
80 let mut last_handshake = None;
81 let mut rx_bytes = None;
82 let mut tx_bytes = None;
83 let mut allowed_ips = Vec::default();
84
85 for attr in wg_peer.iter() {
86 match attr {
87 WgPeerAttrs::PublicKey(v) => public_key = Some(Key::from(v)),
88 WgPeerAttrs::PresharedKey(v) => preshared_key = Some(Key::from(v)),
89 WgPeerAttrs::Endpoint(v) => endpoint = Some(*v),
90 WgPeerAttrs::PersistentKeepalive(v) => persistent_keepalive = Some(*v),
91 WgPeerAttrs::LastHandshake(v) => last_handshake = Some(*v),
92 WgPeerAttrs::RxBytes(v) => rx_bytes = Some(*v),
93 WgPeerAttrs::TxBytes(v) => tx_bytes = Some(*v),
94 WgPeerAttrs::AllowedIps(v) => {
95 for ip in v {
96 allowed_ips.push(ipnet_from_wg(ip)?);
97 }
98 }
99 _ => {}
100 }
101 }
102
103 Ok(PeerView {
104 public_key: public_key.ok_or_else(|| Error::message("missing public_key"))?,
105 preshared_key,
106 endpoint,
107 persistent_keepalive,
108 last_handshake: last_handshake.ok_or_else(|| Error::message("missing last_handshake"))?,
109 rx_bytes: rx_bytes.ok_or_else(|| Error::message("missing rx_bytes"))?,
110 tx_bytes: tx_bytes.ok_or_else(|| Error::message("missing tx_bytes"))?,
111 allowed_ips,
112 })
113}
114
115fn ipnet_from_wg(wg: &WgAllowedIp) -> Result<IpNet> {
116 let mut ip = None;
117 let mut prefix = None;
118 for attr in wg.iter() {
119 match attr {
120 WgAllowedIpAttrs::IpAddr(v) => ip = Some(*v),
121 WgAllowedIpAttrs::Cidr(v) => prefix = Some(*v),
122 _ => {}
123 }
124 }
125 Ok(IpNet::new(
126 ip.ok_or_else(|| Error::message("missing ip"))?,
127 prefix.ok_or_else(|| Error::message("missing prefix"))?,
128 )
129 .map_err(|e| Error::with_message(e, "invalid ipnet"))?)
130}