wireguard_conf/models/
peer.rs1use derive_builder::Builder;
2use either::Either;
3use ipnet::IpNet;
4
5use std::fmt;
6use std::net::{IpAddr, Ipv6Addr};
7use std::{convert::Infallible, net::Ipv4Addr};
8
9#[cfg(feature = "serde")]
10#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
11use serde::{Deserialize, Serialize};
12
13use crate::prelude::*;
14
15#[derive(Clone, Copy, Debug, PartialEq, Default)]
17#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
18pub struct ToInterfaceOptions {
19 default_gateway: bool,
21
22 persistent_keepalive: u16,
24
25 #[cfg(feature = "amneziawg")]
27 strip_server_data: bool,
28}
29
30impl ToInterfaceOptions {
31 #[must_use]
33 pub fn new() -> Self {
34 Self::default()
35 }
36
37 #[must_use]
41 pub fn default_gateway(mut self, value: bool) -> Self {
42 self.default_gateway = value;
43 self
44 }
45
46 #[must_use]
49 pub fn persistent_keepalive(mut self, value: u16) -> Self {
50 self.persistent_keepalive = value;
51 self
52 }
53
54 #[must_use]
56 #[cfg(feature = "amneziawg")]
57 pub fn strip_server_data(mut self, value: bool) -> Self {
58 self.strip_server_data = value;
59 self
60 }
61}
62
63#[must_use]
67#[derive(Clone, Debug, PartialEq, Builder)]
68#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
69#[builder(build_fn(private, name = "fallible_build", error = "Infallible"))]
70pub struct Peer {
71 #[builder(setter(into, strip_option), default)]
75 pub endpoint: Option<String>,
76
77 #[builder(setter(into), default)]
83 pub allowed_ips: Vec<IpNet>,
84
85 #[builder(default)]
94 pub persistent_keepalive: u16,
95
96 #[builder(default = Either::Left(PrivateKey::random()))]
101 pub key: Either<PrivateKey, PublicKey>,
102
103 #[builder(setter(strip_option), default)]
105 pub preshared_key: Option<PresharedKey>,
106}
107
108impl Peer {
109 #[must_use]
121 pub fn builder() -> PeerBuilder {
122 PeerBuilder::default()
123 }
124}
125
126impl PeerBuilder {
127 #[must_use]
139 pub fn new() -> Self {
140 Self::default()
141 }
142
143 pub fn private_key(&mut self, value: PrivateKey) -> &mut Self {
147 self.key = Some(Either::Left(value));
148 self
149 }
150
151 pub fn public_key(&mut self, value: PublicKey) -> &mut Self {
155 self.key = Some(Either::Right(value));
156 self
157 }
158
159 pub fn build(&self) -> Peer {
161 self.fallible_build().unwrap_or_else(|_| unreachable!())
162 }
163}
164
165impl Peer {
166 pub fn to_interface(
178 &self,
179 server_interface: &Interface,
180 options: ToInterfaceOptions,
181 ) -> WireguardResult<Interface> {
182 let Either::Left(private_key) = self.key.clone() else {
183 return Err(WireguardError::NoPrivateKeyProvided);
184 };
185
186 let assigned_ips: Vec<IpNet> = self
187 .allowed_ips
188 .iter()
189 .filter_map(|allowed_ip| {
190 for server_address in &server_interface.address {
191 if server_address.contains(allowed_ip) {
192 return IpNet::new(allowed_ip.addr(), server_address.prefix_len()).ok();
193 }
194 }
195
196 None
197 })
198 .collect();
199
200 if assigned_ips.is_empty() {
201 return Err(WireguardError::NoAssignedIP);
202 }
203
204 let mut client_interface = Interface {
205 endpoint: None,
206
207 address: assigned_ips.clone(),
208 listen_port: None,
209 private_key,
210 dns: server_interface.dns.clone(),
211
212 table: None,
213 mtu: None,
214
215 #[cfg(feature = "amneziawg")]
216 amnezia_settings: server_interface.amnezia_settings.clone(),
217
218 pre_up: vec![],
219 pre_down: vec![],
220 post_up: vec![],
221 post_down: vec![],
222
223 peers: vec![server_interface.to_peer()],
224 };
225
226 if options.default_gateway {
227 client_interface.peers[0].allowed_ips = {
228 let mut allowed_ips = Vec::with_capacity(1);
229
230 if assigned_ips.iter().any(|ip| ip.addr().is_ipv4()) {
231 allowed_ips.push(IpNet::new_assert(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0));
232 }
233
234 if assigned_ips.iter().any(|ip| ip.addr().is_ipv6()) {
235 allowed_ips.push(IpNet::new_assert(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0));
236 }
237
238 allowed_ips
239 };
240 }
241
242 if options.persistent_keepalive != 0 {
243 client_interface.peers[0].persistent_keepalive = options.persistent_keepalive;
244 }
245
246 #[cfg(feature = "amneziawg")]
247 if options.strip_server_data
248 && let Some(settings) = &mut client_interface.amnezia_settings
249 {
250 settings.strip_server_data();
251 }
252
253 Ok(client_interface)
254 }
255}
256
257impl fmt::Display for Peer {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 writeln!(f, "[Peer]")?;
266 if let Some(endpoint) = self.endpoint.clone() {
267 writeln!(f, "Endpoint = {endpoint}")?;
268 }
269 writeln!(
270 f,
271 "AllowedIPs = {}",
272 self.allowed_ips
273 .iter()
274 .map(std::string::ToString::to_string)
275 .collect::<Vec<String>>()
276 .join(",")
277 )?;
278 writeln!(
279 f,
280 "PublicKey = {}",
281 self.key.clone().right_or_else(|key| PublicKey::from(&key))
282 )?;
283 if let Some(preshared_key) = &self.preshared_key {
284 writeln!(f, "PresharedKey = {preshared_key}")?;
285 }
286 if self.persistent_keepalive != 0 {
287 writeln!(f, "PersistentKeepalive = {}", self.persistent_keepalive)?;
288 }
289
290 Ok(())
291 }
292}