diff options
-rw-r--r-- | src/config.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 18 | ||||
-rw-r--r-- | src/manager/builder.rs | 75 | ||||
-rw-r--r-- | src/proto.rs | 23 |
4 files changed, 78 insertions, 44 deletions
diff --git a/src/config.rs b/src/config.rs index 362c962..7b3aa4b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // -// Copyright 2019 Hristo Venev +// Copyright 2019,2020 Hristo Venev -use crate::model::{Ipv4Set, Ipv6Set, Key, Secret}; +use crate::model::{Endpoint, Ipv4Set, Ipv6Set, Key, Secret}; use serde_derive; use std::collections::HashMap; use std::path::PathBuf; @@ -22,7 +22,9 @@ pub struct Source { #[serde(deny_unknown_fields)] pub struct Peer { pub source: Option<String>, + pub endpoint: Option<Endpoint>, pub psk: Option<Secret>, + pub keepalive: Option<u32>, } #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/src/main.rs b/src/main.rs index 8ab9fb3..462da48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,13 +62,25 @@ fn cli_config(mut args: impl Iterator<Item = OsString>) -> Option<config::Config } } State::Peer(ref mut p) => { + if key == "source" { + p.source = Some(args.next()?.into_string().ok()?); + continue; + } + if key == "endpoint" { + arg = args.next()?; + let arg = arg.to_str()?; + p.endpoint = Some(model::Endpoint::from_str(arg).ok()?); + continue; + } if key == "psk" { arg = args.next()?; p.psk = Some(model::Secret::new(arg.into())); continue; } - if key == "source" { - p.source = Some(args.next()?.into_string().ok()?); + if key == "keepalive" { + arg = args.next()?; + let arg = arg.to_str()?; + p.keepalive = Some(u32::from_str(arg).ok()?); continue; } } @@ -111,7 +123,9 @@ fn cli_config(mut args: impl Iterator<Item = OsString>) -> Option<config::Config let key = model::Key::from_str(arg.to_str()?).ok()?; cur = State::Peer(cfg.global.peers.entry(key).or_insert(config::Peer { source: None, + endpoint: None, psk: None, + keepalive: None, })); continue; } diff --git a/src/manager/builder.rs b/src/manager/builder.rs index 4f0e667..9c2ad15 100644 --- a/src/manager/builder.rs +++ b/src/manager/builder.rs @@ -49,6 +49,12 @@ impl fmt::Display for Error { } } +struct PeerContact<'a> { + endpoint: Option<model::Endpoint>, + psk: Option<&'a model::Secret>, + keepalive: u32, +} + pub(super) struct ConfigBuilder<'a> { c: model::Config, err: Vec<Error>, @@ -76,29 +82,28 @@ impl<'a> ConfigBuilder<'a> { pub fn add_server(&mut self, src: &Source, p: &proto::Server) { let gc = self.gc; - let psk = match find_psk(gc, src, &p.peer) { + let mut contact = match peer_contact(gc, src, &p.peer) { Ok(v) => v, Err(e) => { self.err.push(e); return; } }; + if contact.endpoint.is_none() { + contact.endpoint = Some(p.endpoint); + } if p.peer.public_key == self.public_key { return; } - let ent = insert_peer(&mut self.c, &mut self.err, src, &p.peer, psk, |ent| { - ent.endpoint = Some(p.endpoint); - ent.keepalive = gc.fix_keepalive(p.keepalive); - }); - + let ent = insert_peer(&mut self.c, &mut self.err, src, &p.peer, contact); add_peer(&mut self.err, ent, src, &p.peer) } #[inline] pub fn add_road_warrior(&mut self, src: &Source, p: &proto::RoadWarrior) { - let psk = match find_psk(self.gc, src, &p.peer) { + let contact = match peer_contact(self.gc, src, &p.peer) { Ok(v) => v, Err(e) => { self.err.push(e); @@ -117,7 +122,7 @@ impl<'a> ConfigBuilder<'a> { } let ent = if p.base == self.public_key { - insert_peer(&mut self.c, &mut self.err, src, &p.peer, psk, |_| {}) + insert_peer(&mut self.c, &mut self.err, src, &p.peer, contact) } else if let Some(ent) = self.c.peers.get_mut(&p.base) { ent } else { @@ -135,45 +140,55 @@ fn insert_peer<'b>( err: &mut Vec<Error>, src: &Source, p: &proto::Peer, - psk: Option<&model::Secret>, - update: impl for<'c> FnOnce(&'c mut model::Peer) -> (), + contact: PeerContact<'_>, ) -> &'b mut model::Peer { match c.peers.entry(p.public_key) { hash_map::Entry::Occupied(ent) => { err.push(Error::new("duplicate public key", src, p, true)); ent.into_mut() } - hash_map::Entry::Vacant(ent) => { - let ent = ent.insert(model::Peer { - endpoint: None, - psk: psk.cloned(), - keepalive: 0, - ipv4: vec![], - ipv6: vec![], - }); - update(ent); - ent - } + hash_map::Entry::Vacant(ent) => ent.insert(model::Peer { + endpoint: contact.endpoint, + psk: contact.psk.cloned(), + keepalive: contact.keepalive, + ipv4: vec![], + ipv6: vec![], + }), } } -fn find_psk<'a>( +fn peer_contact<'a>( gc: &'a config::GlobalConfig, src: &'a Source, p: &proto::Peer, -) -> Result<Option<&'a model::Secret>, Error> { - let want = match gc.peers.get(&p.public_key) { - Some(v) => v, - None => return Ok(None), +) -> Result<PeerContact<'a>, Error> { + let mut r = PeerContact { + psk: src.config.psk.as_ref(), + endpoint: None, + keepalive: gc.fix_keepalive(p.keepalive), }; - if let Some(ref want_src) = &want.source { - if *want_src != src.name { - return Err(Error::new("peer source not allowed", src, p, true)); + if let Some(pc) = gc.peers.get(&p.public_key) { + if let Some(ref want_src) = &pc.source { + if *want_src != src.name { + return Err(Error::new("peer source not allowed", src, p, true)); + } + } + + if let Some(endpoint) = pc.endpoint { + r.endpoint = Some(endpoint); + } + + if let Some(ref psk) = &pc.psk { + r.psk = Some(psk); + } + + if let Some(keepalive) = pc.keepalive { + r.keepalive = keepalive; } } - Ok(want.psk.as_ref().or_else(|| src.config.psk.as_ref())) + Ok(r) } fn add_peer(err: &mut Vec<Error>, ent: &mut model::Peer, src: &Source, p: &proto::Peer) { diff --git a/src/proto.rs b/src/proto.rs index 9f9ea0a..5f168a9 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -11,6 +11,7 @@ pub struct Peer { pub public_key: Key, pub ipv4: Vec<Ipv4Net>, pub ipv6: Vec<Ipv6Net>, + pub keepalive: u32, } #[serde(from = "ServerRepr", into = "ServerRepr")] @@ -18,7 +19,6 @@ pub struct Peer { pub struct Server { pub peer: Peer, pub endpoint: Endpoint, - pub keepalive: u32, } #[derive(serde_derive::Serialize, serde_derive::Deserialize)] @@ -29,23 +29,20 @@ struct ServerRepr { ipv4: Vec<Ipv4Net>, #[serde(default)] ipv6: Vec<Ipv6Net>, - endpoint: Endpoint, #[serde(default)] keepalive: u32, + endpoint: Endpoint, } impl From<Server> for ServerRepr { #[inline] fn from(v: Server) -> Self { - let Server { - peer, - endpoint, - keepalive, - } = v; + let Server { peer, endpoint } = v; let Peer { public_key, ipv4, ipv6, + keepalive, } = peer; Self { public_key, @@ -64,17 +61,17 @@ impl From<ServerRepr> for Server { public_key, ipv4, ipv6, - endpoint, keepalive, + endpoint, } = v; Self { peer: Peer { public_key, ipv4, ipv6, + keepalive, }, endpoint, - keepalive, } } } @@ -94,7 +91,9 @@ pub struct RoadWarriorRepr { ipv4: Vec<Ipv4Net>, #[serde(default)] ipv6: Vec<Ipv6Net>, - pub base: Key, + #[serde(default)] + keepalive: u32, + base: Key, } impl From<RoadWarrior> for RoadWarriorRepr { @@ -105,11 +104,13 @@ impl From<RoadWarrior> for RoadWarriorRepr { public_key, ipv4, ipv6, + keepalive, } = peer; Self { public_key, ipv4, ipv6, + keepalive, base, } } @@ -122,6 +123,7 @@ impl From<RoadWarriorRepr> for RoadWarrior { public_key, ipv4, ipv6, + keepalive, base, } = v; Self { @@ -129,6 +131,7 @@ impl From<RoadWarriorRepr> for RoadWarrior { public_key, ipv4, ipv6, + keepalive, }, base, } |