1use crate::xplatform::protocol::SetKey;
2use std::fmt::Display;
3use std::net::IpAddr;
4use std::net::SocketAddr;
5
6#[derive(Debug, Default, PartialEq, Eq)]
9pub struct Device {
10 pub private_key: Option<[u8; 32]>,
15
16 pub listen_port: Option<u16>,
19
20 pub fwmark: Option<u32>,
24
25 pub replace_peers: Option<bool>,
29
30 pub peers: Vec<Peer>,
31}
32
33impl Display for Device {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 if let Some(private_key) = self.private_key {
36 let private_key = hex::encode(private_key);
37 writeln!(f, "{}={}", SetKey::PrivateKey, private_key)?;
38 }
39
40 if let Some(listen_port) = self.listen_port {
41 writeln!(f, "{}={}", SetKey::ListenPort, listen_port)?;
42 }
43
44 if let Some(fwmark) = self.fwmark {
45 writeln!(f, "{}={}", SetKey::Fwmark, fwmark)?;
46 }
47
48 if let Some(replace_peers) = self.replace_peers {
49 writeln!(f, "{}={}", SetKey::ReplacePeers, replace_peers)?;
50 }
51
52 for peer in &self.peers {
53 peer.fmt(f)?;
54 }
55
56 Ok(())
57 }
58}
59
60#[derive(Clone, Debug, Default, PartialEq, Eq)]
63pub struct Peer {
64 pub public_key: [u8; 32],
68
69 pub remove: Option<bool>,
73
74 pub update_only: Option<bool>,
78
79 pub preshared_key: Option<[u8; 32]>,
84
85 pub endpoint: Option<SocketAddr>,
88
89 pub persistent_keepalive_interval: Option<u16>,
93
94 pub replace_allowed_ips: Option<bool>,
99
100 pub allowed_ips: Vec<AllowedIp>,
105}
106
107impl Peer {
108 pub fn from_public_key(public_key: [u8; 32]) -> Self {
109 Self {
110 public_key,
111 remove: None,
112 update_only: None,
113 preshared_key: None,
114 endpoint: None,
115 persistent_keepalive_interval: None,
116 replace_allowed_ips: None,
117 allowed_ips: vec![],
118 }
119 }
120
121 pub fn remove(mut self, remove: bool) -> Self {
122 self.remove = remove.then_some(true);
123 self
124 }
125
126 pub fn update_only(mut self, update_only: bool) -> Self {
127 self.update_only = update_only.then_some(true);
128 self
129 }
130
131 pub fn preshared_key(mut self, preshared_key: [u8; 32]) -> Self {
132 self.preshared_key = Some(preshared_key);
133 self
134 }
135
136 pub fn endpoint(mut self, endpoint: SocketAddr) -> Self {
137 self.endpoint = Some(endpoint);
138 self
139 }
140
141 pub fn persistent_keepalive_interval(mut self, persistent_keepalive_interval: u16) -> Self {
142 self.persistent_keepalive_interval = Some(persistent_keepalive_interval);
143 self
144 }
145
146 pub fn replace_allowed_ips(mut self, replace_allowed_ips: bool) -> Self {
147 self.replace_allowed_ips = replace_allowed_ips.then_some(true);
148 self
149 }
150
151 pub fn allowed_ips(mut self, allowed_ips: Vec<AllowedIp>) -> Self {
152 self.allowed_ips = allowed_ips;
153 self
154 }
155}
156
157impl Display for Peer {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 writeln!(f, "{}={}", SetKey::PublicKey, hex::encode(self.public_key))?;
160
161 if let Some(remove) = self.remove {
162 writeln!(f, "{}={}", SetKey::Remove, remove)?;
163 }
164
165 if let Some(update_only) = self.update_only {
166 writeln!(f, "{}={}", SetKey::UpdateOnly, update_only)?;
167 }
168
169 if let Some(preshared_key) = self.preshared_key {
170 let preshared_key = hex::encode(preshared_key);
171 writeln!(f, "{}={}", SetKey::PresharedKey, preshared_key)?;
172 }
173
174 if let Some(endpoint) = self.endpoint {
175 writeln!(f, "{}={}", SetKey::Endpoint, endpoint)?;
176 }
177
178 if let Some(interval) = self.persistent_keepalive_interval {
179 writeln!(f, "{}={}", SetKey::PersistentKeepaliveInterval, interval)?;
180 }
181
182 if let Some(replace_allowed_ips) = self.replace_allowed_ips {
183 writeln!(f, "{}={}", SetKey::ReplaceAllowedIps, replace_allowed_ips)?;
184 }
185
186 for allowed_ip in &self.allowed_ips {
187 allowed_ip.fmt(f)?;
188 }
189
190 Ok(())
191 }
192}
193
194#[derive(Clone, Debug, PartialEq, Eq)]
195pub struct AllowedIp {
196 pub ipaddr: IpAddr,
197 pub cidr_mask: u8,
198}
199
200impl Display for AllowedIp {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 writeln!(
203 f,
204 "{}={}/{}",
205 SetKey::AllowedIp,
206 self.ipaddr,
207 self.cidr_mask
208 )
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 #[test]
217 fn serialize_website_example() {
218 let expected = "\
221 private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a\n\
222 listen_port=12912\n\
223 fwmark=0\n\
224 replace_peers=true\n\
225 public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33\n\
226 preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52\n\
227 endpoint=[abcd:23::33%2]:51820\n\
228 replace_allowed_ips=true\n\
229 allowed_ip=192.168.4.4/32\n\
230 public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376\n\
231 endpoint=182.122.22.19:3233\n\
232 persistent_keepalive_interval=111\n\
233 replace_allowed_ips=true\n\
234 allowed_ip=192.168.4.6/32\n\
235 public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58\n\
236 endpoint=5.152.198.39:51820\n\
237 replace_allowed_ips=true\n\
238 allowed_ip=192.168.4.10/32\n\
239 allowed_ip=192.168.4.11/32\n\
240 public_key=e818b58db5274087fcc1be5dc728cf53d3b5726b4cef6b9bab8f8f8c2452c25c\n\
241 remove=true\n";
242
243 let set_request = Device {
244 private_key: Some([
245 0xe8, 0x4b, 0x5a, 0x6d, 0x27, 0x17, 0xc1, 0x00, 0x3a, 0x13, 0xb4, 0x31, 0x57, 0x03,
246 0x53, 0xdb, 0xac, 0xa9, 0x14, 0x6c, 0xf1, 0x50, 0xc5, 0xf8, 0x57, 0x56, 0x80, 0xfe,
247 0xba, 0x52, 0x02, 0x7a,
248 ]),
249 listen_port: Some(12912),
250 fwmark: Some(0),
251 replace_peers: Some(true),
252 peers: vec![
253 Peer::from_public_key([
254 0xb8, 0x59, 0x96, 0xfe, 0xcc, 0x9c, 0x7f, 0x1f, 0xc6, 0xd2, 0x57, 0x2a, 0x76,
255 0xed, 0xa1, 0x1d, 0x59, 0xbc, 0xd2, 0x0b, 0xe8, 0xe5, 0x43, 0xb1, 0x5c, 0xe4,
256 0xbd, 0x85, 0xa8, 0xe7, 0x5a, 0x33,
257 ])
258 .preshared_key([
259 0x18, 0x85, 0x15, 0x09, 0x3e, 0x95, 0x2f, 0x5f, 0x22, 0xe8, 0x65, 0xce, 0xf3,
260 0x01, 0x2e, 0x72, 0xf8, 0xb5, 0xf0, 0xb5, 0x98, 0xac, 0x03, 0x09, 0xd5, 0xda,
261 0xcc, 0xe3, 0xb7, 0x0f, 0xcf, 0x52,
262 ])
263 .replace_allowed_ips(true)
264 .allowed_ips(vec![AllowedIp {
265 ipaddr: "192.168.4.4".parse().unwrap(),
266 cidr_mask: 32,
267 }])
268 .endpoint("[abcd:23::33%2]:51820".parse().unwrap()),
269 Peer::from_public_key([
270 0x58, 0x40, 0x2e, 0x69, 0x5b, 0xa1, 0x77, 0x2b, 0x1c, 0xc9, 0x30, 0x97, 0x55,
271 0xf0, 0x43, 0x25, 0x1e, 0xa7, 0x7f, 0xdc, 0xf1, 0x0f, 0xbe, 0x63, 0x98, 0x9c,
272 0xeb, 0x7e, 0x19, 0x32, 0x13, 0x76,
273 ])
274 .replace_allowed_ips(true)
275 .allowed_ips(vec![AllowedIp {
276 ipaddr: "192.168.4.6".parse().unwrap(),
277 cidr_mask: 32,
278 }])
279 .persistent_keepalive_interval(111)
280 .endpoint("182.122.22.19:3233".parse().unwrap()),
281 Peer::from_public_key([
282 0x66, 0x2e, 0x14, 0xfd, 0x59, 0x45, 0x56, 0xf5, 0x22, 0x60, 0x47, 0x03, 0x34,
283 0x03, 0x51, 0x25, 0x89, 0x03, 0xb6, 0x4f, 0x35, 0x55, 0x37, 0x63, 0xf1, 0x94,
284 0x26, 0xab, 0x2a, 0x51, 0x5c, 0x58,
285 ])
286 .endpoint("5.152.198.39:51820".parse().unwrap())
287 .replace_allowed_ips(true)
288 .allowed_ips(vec![
289 AllowedIp {
290 ipaddr: "192.168.4.10".parse().unwrap(),
291 cidr_mask: 32,
292 },
293 AllowedIp {
294 ipaddr: "192.168.4.11".parse().unwrap(),
295 cidr_mask: 32,
296 },
297 ]),
298 Peer::from_public_key([
299 0xe8, 0x18, 0xb5, 0x8d, 0xb5, 0x27, 0x40, 0x87, 0xfc, 0xc1, 0xbe, 0x5d, 0xc7,
300 0x28, 0xcf, 0x53, 0xd3, 0xb5, 0x72, 0x6b, 0x4c, 0xef, 0x6b, 0x9b, 0xab, 0x8f,
301 0x8f, 0x8c, 0x24, 0x52, 0xc2, 0x5c,
302 ])
303 .remove(true),
304 ],
305 };
306 let actual = format!("{set_request}");
307
308 assert_eq!(expected, actual);
309 }
310
311 #[test]
312 fn serialize_update_only() {
313 let expected = [
314 "private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a",
315 "public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33",
316 "update_only=true",
317 "endpoint=[abcd:23::33%2]:51820",
318 "replace_allowed_ips=true",
319 "allowed_ip=192.168.4.4/32",
320 "",
321 ]
322 .join("\n");
323
324 let set_request = Device {
325 private_key: Some([
326 0xe8, 0x4b, 0x5a, 0x6d, 0x27, 0x17, 0xc1, 0x00, 0x3a, 0x13, 0xb4, 0x31, 0x57, 0x03,
327 0x53, 0xdb, 0xac, 0xa9, 0x14, 0x6c, 0xf1, 0x50, 0xc5, 0xf8, 0x57, 0x56, 0x80, 0xfe,
328 0xba, 0x52, 0x02, 0x7a,
329 ]),
330 peers: vec![Peer::from_public_key([
331 0xb8, 0x59, 0x96, 0xfe, 0xcc, 0x9c, 0x7f, 0x1f, 0xc6, 0xd2, 0x57, 0x2a, 0x76, 0xed,
332 0xa1, 0x1d, 0x59, 0xbc, 0xd2, 0x0b, 0xe8, 0xe5, 0x43, 0xb1, 0x5c, 0xe4, 0xbd, 0x85,
333 0xa8, 0xe7, 0x5a, 0x33,
334 ])
335 .update_only(true)
336 .replace_allowed_ips(true)
337 .allowed_ips(vec![AllowedIp {
338 ipaddr: "192.168.4.4".parse().unwrap(),
339 cidr_mask: 32,
340 }])
341 .endpoint("[abcd:23::33%2]:51820".parse().unwrap())],
342 ..Default::default()
343 };
344 let actual = format!("{set_request}");
345
346 assert_eq!(expected, actual);
347 }
348
349 #[test]
351 fn cover_derives() {
352 let device1 = Device::default();
353 let device2 = Device::default();
354 assert_eq!(device1, device2);
355 let _ = format!("{device1:?}");
356
357 let peer1 = Peer::from_public_key([
358 0xb8, 0x59, 0x96, 0xfe, 0xcc, 0x9c, 0x7f, 0x1f, 0xc6, 0xd2, 0x57, 0x2a, 0x76, 0xed,
359 0xa1, 0x1d, 0x59, 0xbc, 0xd2, 0x0b, 0xe8, 0xe5, 0x43, 0xb1, 0x5c, 0xe4, 0xbd, 0x85,
360 0xa8, 0xe7, 0x5a, 0x33,
361 ]);
362 let peer2 = Peer::from_public_key([
363 0xb8, 0x59, 0x96, 0xfe, 0xcc, 0x9c, 0x7f, 0x1f, 0xc6, 0xd2, 0x57, 0x2a, 0x76, 0xed,
364 0xa1, 0x1d, 0x59, 0xbc, 0xd2, 0x0b, 0xe8, 0xe5, 0x43, 0xb1, 0x5c, 0xe4, 0xbd, 0x85,
365 0xa8, 0xe7, 0x5a, 0x33,
366 ]);
367 assert_eq!(peer1, peer2);
368 let _ = format!("{peer1:?}");
369
370 let allowed_ip1 = AllowedIp {
371 ipaddr: "::1".parse().unwrap(),
372 cidr_mask: 64,
373 };
374 let allowed_ip2 = AllowedIp {
375 ipaddr: "::1".parse().unwrap(),
376 cidr_mask: 64,
377 };
378 assert_eq!(allowed_ip1, allowed_ip2);
379 let _ = format!("{allowed_ip1:?}");
380 }
381}