1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
use base64::prelude::*;
use dbus::{channel::MatchingReceiver, message::MatchRule};
use dbus_crossroads::{Context, Crossroads, MethodErr};
use defguard_wireguard_rs::{
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
};
use log::{debug, error, info, warn};
use rand::Rng;
use std::{
collections::{BTreeSet, HashMap},
marker::PhantomData,
ops::DerefMut,
str::FromStr,
sync::Arc,
};
use tokio::{
net::TcpListener,
sync::{broadcast, RwLock},
task,
};
use crate::{daemon::*, daemon_network::*};
// TODO also take peers
pub async fn handle_add_network(
mut ctx: Context,
state: Arc<RwLock<State>>,
(name, may_key, may_ip, may_lp, may_mp): (String, String, String, u16, u16),
) -> PhantomData<(bool,)> {
// NOTE: this is kinda stupid: we convert to a string later anyways, as thats what
// defguard_wg takes...
let key = Key::new(match may_key.as_str() {
"" => rand::thread_rng().gen(),
_ => match BASE64_STANDARD.decode(may_key) {
Ok(v) if v.len() == 32 => v.try_into().unwrap(),
_ => {
warn!("AddNetwork with bad key");
return ctx.reply(Err(MethodErr::invalid_arg("bad key")));
}
},
});
// we store the ip as the original string, but should validate it regardless
let (ip, ip_string) = match may_ip.as_str() {
"" => todo!(),
_ => match IpAddrMask::from_str(&may_ip) {
Ok(ip_mask) => (ip_mask.ip, may_ip),
Err(_) => {
warn!("AddNetwork with bad ip");
return ctx.reply(Err(MethodErr::invalid_arg("invalid ip")));
}
},
};
let lp = if may_lp == 0 { 25565 } else { may_lp };
let mp = if may_mp == 0 { 51820 } else { may_mp };
let mut state_rw_guard = state.write().await;
let state_rw = state_rw_guard.deref_mut();
let wg_api = match add_network(
&mut state_rw.hostfile,
name.clone(),
key.to_string(),
ip_string,
lp,
&HashMap::new(),
)
.await
{
Ok(wg_api) => wg_api,
Err(e) => {
warn!("AddNetwork couldn't add network: {e}");
return ctx.reply(Err(MethodErr::failed(&e)));
}
};
// TODO ins wg_api
let listener = match TcpListener::bind((ip, mp)).await {
Ok(l) => l,
Err(e) => {
let _ = wg_api.remove_interface();
warn!("AddNetwork couldn't start listener: {e}");
return ctx.reply(Err(MethodErr::failed(&e)));
}
};
let h = task::spawn(print_error(run_network(
state.clone(),
listener,
name.clone(),
)));
state_rw.nw_handles.insert(name.clone(), (wg_api, h));
// TODO save new config
ctx.reply(Ok((true,)))
}
|