diff options
Diffstat (limited to 'src/daemon_dbus.rs')
-rw-r--r-- | src/daemon_dbus.rs | 135 |
1 files changed, 113 insertions, 22 deletions
diff --git a/src/daemon_dbus.rs b/src/daemon_dbus.rs index 5ed4d94..f0873f0 100644 --- a/src/daemon_dbus.rs +++ b/src/daemon_dbus.rs @@ -1,4 +1,3 @@ -use base64::prelude::*; use dbus::{ channel::{MatchingReceiver, Token}, message::MatchRule, @@ -22,7 +21,11 @@ pub async fn start_dbus( ) -> Result<(Arc<SyncConnection>, Token), DaemonError> { let mut cr = Crossroads::new(); let if_token = cr.register("de.a.maesch", move |b| { - b.signal::<(String, String), _>("Proposal", ("network", "peer_data")); + //b.signal::<(String, String), _>("Proposal", ("network", "peer_data")); + + let state_rem_network = state.clone(); + let config_path_rem_network = config_path.clone(); + b.method_with_cr_async( "AddNetwork", ("name", "key", "ip", "listen_port", "maesch_port"), @@ -32,6 +35,20 @@ pub async fn start_dbus( handle_add_network(ctx, state.clone(), config_path.clone(), args) }, ); + b.method_with_cr_async( + "RemoveNetwork", + ("name",), + ("success",), + move |ctx, _, args: (String,)| { + debug!("Received RemoveNetwork"); + handle_remove_network( + ctx, + state_rem_network.clone(), + config_path_rem_network.clone(), + args, + ) + }, + ); }); cr.insert("/de/a/maesch", &[if_token], ()); @@ -59,29 +76,84 @@ pub async fn start_dbus( Ok((c, receive_token)) } -// TODO also take peers +pub async fn handle_remove_network( + mut ctx: Context, + state: Arc<RwLock<State>>, + config_path: PathBuf, + (name,): (String,), +) -> PhantomData<(bool,)> { + let mut state_rw_guard = state.write().await; + + if let Some(_) = state_rw_guard.conf.networks.remove(&name) { + let (wg_api, h) = state_rw_guard + .nw_handles + .remove(&name) + .expect("state.conf.networks and state.nw_handles desynced"); + h.abort(); + + let ri = wg_api.remove_interface(); + let _ = h.await; + + match write_config(&state_rw_guard.conf, &config_path) { + Ok(_) => info!("Synced config"), + Err(e) => { + error!("Couldn't sync config: {e}"); + return ctx.reply(Err(MethodErr::failed(&e))); + } + }; + drop(state_rw_guard); + + match ri { + Ok(_) => info!("Removed network: {name}"), + Err(e) => { + error!("Removing network: {e}"); + return ctx.reply(Err(MethodErr::failed(&e))); + } + }; + } else { + warn!("Tried to remove non-existent network: {name}"); + return ctx.reply(Err(MethodErr::invalid_arg("bad network"))); + } + + ctx.reply(Ok((true,))) +} + +// TODO make this merge correctly... pub async fn handle_add_network( mut ctx: Context, state: Arc<RwLock<State>>, config_path: PathBuf, (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"))); - } - }, - }); + let mut state_rw_guard = state.write().await; + let state_rw = state_rw_guard.deref_mut(); + + // TODO do more with the entry... + let prev_entry = state_rw.conf.networks.remove(&name); + + let key = if may_key.as_str() == "" { + prev_entry + .as_ref() + .map(|nw| nw.privkey.clone()) + .unwrap_or_else(|| Key::new(rand::thread_rng().gen()).to_string()) + } else { + may_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 prev_entry.as_ref() { + Some(e) => ( + IpAddrMask::from_str(&e.address) + .expect("Impossible: old config broken!") + .ip, + e.address.clone(), + ), + None => { + warn!("AddNetwork with no ip"); + return ctx.reply(Err(MethodErr::invalid_arg("ip required"))); + } + }, _ => match IpAddrMask::from_str(&may_ip) { Ok(ip_mask) => (ip_mask.ip, may_ip), Err(_) => { @@ -91,13 +163,24 @@ pub async fn handle_add_network( }, }; - let lp = if may_lp == 0 { 25565 } else { may_lp }; - let mp = if may_mp == 0 { 51820 } else { may_mp }; + let lp = if may_lp == 0 { + prev_entry + .as_ref() + .map(|nw| nw.listen_port) + .unwrap_or(25565) + } else { + may_lp + }; + let mp = if may_mp == 0 { + prev_entry.as_ref().map(|nw| nw.mäsch_port).unwrap_or(51820) + } else { + may_mp + }; let (wg_api, hostnames) = match add_network( name.clone(), - key.to_string(), - ip_string, + key.clone(), + ip_string.clone(), lp, &HashMap::new(), ) @@ -124,9 +207,17 @@ pub async fn handle_add_network( name.clone(), ))); - let mut state_rw_guard = state.write().await; - let state_rw = state_rw_guard.deref_mut(); state_rw.nw_handles.insert(name.clone(), (wg_api, h)); + state_rw.conf.networks.insert( + name, + Network { + privkey: key, + address: ip_string, + listen_port: lp, + peers: prev_entry.map_or_else(|| HashMap::new(), |nw| nw.peers), + mäsch_port: mp, + }, + ); // NOTE this _is_ thread-safe, as we hold an exclusive write handle to the state. match write_config(&state_rw.conf, &config_path) { |