basic strcuture [CI SKIP]

This commit is contained in:
Drone CI 2019-03-19 12:05:31 +01:00
parent fc494fe4c0
commit 7491902b34
3 changed files with 78 additions and 44 deletions

View File

@ -1,6 +1,9 @@
use crate::model::WireguardController; use crate::model::{ECCKey, Peer, PeerBuilder, WireguardController};
use std::io::{BufRead, BufReader, Result, Write};
use std::net::{IpAddr, SocketAddr};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration;
pub struct Userspace(PathBuf); pub struct Userspace(PathBuf);
@ -11,36 +14,50 @@ impl Userspace {
} }
impl WireguardController for Userspace { impl WireguardController for Userspace {
fn peers<'a>(&'a mut self) -> Box<Iterator<Item = Result<Peer>> + 'a> { fn peers<'a>(&'a mut self) -> Result<Box<Iterator<Item = Result<Peer>> + 'a>> {
let mut stream = UnixStream::connect(&self.0)?; let mut stream = UnixStream::connect(&self.0)?;
stream.write_all(b"get=1\n")?; stream.write_all(b"get=1\n")?;
fn build_peer(builder: &mut PeerBuilder, line: String) -> Result<()> { fn build_peer(builder: &mut PeerBuilder, line: io::Result<String>) -> Option<Result<Peer>> {
let line = line?; let line = line?;
let mut iter = line.chars(); let mut iter = line.chars();
let key = iter.by_ref().take_while(|c| c != &'=').collect::<String>(); let key = iter.by_ref().take_while(|c| c != &'=').collect::<String>();
let value = iter.collect::<String>(); let value = iter.collect::<String>();
let mut allowed_ips: Vec<(IpAddr, u8)> = Vec::new(); let mut ips: Vec<(IpAddr, u8)> = Vec::with_capacity(0);
let mut last_handshake: Option<Duration> = None; if builder.allowed_ips.len() > 1 {
ips.append(&builder.allowed_ips);
}
let update_handshake = |d: Duration| { let update_handshake = |d: Duration| {
last_handshake = last_handshake.map(|c| c + d); builder.last_handshake(last_handshake.map(|c| c + d));
};
let value_as_num = || value.parse::<usize>();
let mut peer: Option<Peer> = None;
let add_key = |key| {
if builder.key.is_some() {
//If next entry begins
peer = Some(builder.build().map_err(|err: String| {
io::Error::new(ErrorKind::InvalidData, err.into())
})?);
*builder = PeerBuilder::default();
}
builder.key(key);
}; };
match key.as_ref() { match key.as_ref() {
"public_key" => builder.key(ECCKey::from_base64(value)?), "public_key" => add_key(ECCKey::from_base64(value)?),
"private_key" => builder.key(ECCKey::from_base64(value)?), "private_key" => add_key(ECCKey::from_base64(value)?),
"endpoint" => builder.endpoint(value::parse::<SocketAddr>()?), "endpoint" => builder.endpoint(value.parse::<SocketAddr>()?),
"last_handshake_time_sec" => { "last_handshake_time_sec" => {
update_handshake(Duration::from_secs(value::parse::<usize>().into())) update_handshake(Duration::from_secs(value_as_num().into()));
} }
"last_handshake_time_nsec" => { "last_handshake_time_nsec" => {
update_handshake(Duration::from_nsecs(value::parse::<usize>().into())) update_handshake(Duration::from_nanos(value_as_num().into()));
} }
"persistent_keepalive" => { "persistent_keepalive" => {
builder.keepalive(Duration::from_secs(value::parse::<usize>().into())) builder.persistent_keepalive(Some(Duration::from_secs(value_as_num().into())));
} }
"allowed_ip" => { "allowed_ip" => {
let mut parts = value.split("/").into_iter(); let mut parts = value.split("/").into_iter();
let ip = match ( let net = match (
parts.next().and_then(|addr| addr.parse::<IpAddr>().ok()), parts.next().and_then(|addr| addr.parse::<IpAddr>().ok()),
parts.next().and_then(|mask| mask.parse::<u8>().ok()), parts.next().and_then(|mask| mask.parse::<u8>().ok()),
) { ) {
@ -49,17 +66,18 @@ impl WireguardController for Userspace {
(Some(addr), None) => Some((addr, 32)), (Some(addr), None) => Some((addr, 32)),
_ => None, _ => None,
}; };
ips.push(ip); if let Some(net) = net {
builder.allowed_ips.map(|ips| ips.push(net));
} }
} }
builder.allowed_ips(ips); }
builder.last_handshake(last_handshake); peer.map(|peer| Ok(peer))
} }
let peers = BufReader::new(stream) let peers = BufReader::new(stream)
.lines() .lines()
.scan(PeerBuilder::default(), build_peer); .scan(PeerBuilder::default(), build_peer);
loop {} Ok(Box::new(peers))
} }
fn update_peer(&mut self, peer: &Peer) -> Result<()> { fn update_peer(&mut self, peer: &Peer) -> Result<()> {

View File

@ -1,4 +1,11 @@
#[macro_use]
extern crate structopt;
#[macro_use]
extern crate derive_builder;
mod controller; mod controller;
mod model;
use controller::Userspace; use controller::Userspace;

View File

@ -1,47 +1,56 @@
#[macro_use] use base64::decode;
extern crate structopt; use std::error::Error;
use std::io;
use std::net::{IpAddr, SocketAddr};
use std::time::Duration;
use std::time::Instant;
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
#[macro_use] pub enum ECCKey {
extern crate derive_builder;
use std::io::Result;
use base64::{decode};
pub enum ECCKey{
PublicKey([u8; 32]), PublicKey([u8; 32]),
PrivateKey([u8; 32]) PrivateKey([u8; 32]),
} }
impl ECCKey { impl ECCKey {
fn from_base64<I: AsRef<str>>(key: I) -> Result<ECCKey> { pub fn from_base64<I: AsRef<str>>(key: I) -> io::Result<ECCKey> {
let key = decode(key.as_ref::<str>())?; let key = decode(key.as_ref()).map_err(|err| {
io::Error::new(io::ErrorKind::InvalidData, "Failed to decode base64".into())
})?;
let bytes = [0; 32]; let bytes = [0; 32];
bytes.copy_from_slice(key); if key.len() != 32 {
ECCKey::PublicKey(bytes) return Err(io::Error::new(
io::ErrorKind::Other,
"Mismatched key size".into(),
));
}
bytes.copy_from_slice(&key);
Ok(ECCKey::PublicKey(bytes))
} }
} }
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
struct SharedKey([u8; 32]); struct SharedKey([u8; 32]);
#[derive(Debug,Builder, PartialEq, Eq, Hash, Clone)] #[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)]
#[builder(public)]
pub struct Peer { pub struct Peer {
key: ECCKey, key: ECCKey,
#[builder(default = "None")]
shared_key: Option<SharedKey>, shared_key: Option<SharedKey>,
#[builder(default = "None")]
endpoint: Option<SocketAddr>, endpoint: Option<SocketAddr>,
allowed_ips: Vec<(IpAddr, u8)>, allowed_ips: Vec<(IpAddr, u8)>,
last_handshake: Option<Duration>, last_handshake: Option<Duration>,
#[builder(default = "None")]
persistent_keepalive: Option<Duration>, persistent_keepalive: Option<Duration>,
#[builder(default = "(0u64,0u64)")]
traffic: (u64, u64), traffic: (u64, u64),
parsed: time::Timespec, #[builder(default = "Instant::now()")]
parsed: Instant,
} }
pub trait WireguardController {
fn peers<'a>(&'a mut self) -> io::Result<Box<Iterator<Item = io::Result<Peer>> + 'a>>;
trait WireguardController { fn update_peer(&mut self, peer: &Peer) -> io::Result<()>;
fn peers<'a>(&'a mut self) -> Box<Iterator<Item=Result<Peer>> + 'a>;
fn update_peer(&mut self, peer: &Peer) -> Result<()>;
} }