aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHristo Venev <hristo@venev.name>2020-02-04 22:43:44 +0100
committerHristo Venev <hristo@venev.name>2020-02-04 22:43:44 +0100
commite6c406879696a53d40f175d11d14a55d9480a57e (patch)
tree4f91613dbd7f019f33117148177a8a17dc84a94a
parenta7cff9572d672d516569b4a55b4a0dbbeb3cb9e1 (diff)
More peer options in config.
endpoint and keepalive
-rw-r--r--src/config.rs6
-rw-r--r--src/main.rs18
-rw-r--r--src/manager/builder.rs75
-rw-r--r--src/proto.rs23
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,
}