mirror of https://github.com/dswd/vpncloud.git
Updated dependencies
This commit is contained in:
parent
6866c29a71
commit
1f32f0a6a7
|
@ -5,7 +5,9 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
### UNRELEASED
|
### UNRELEASED
|
||||||
|
|
||||||
- [changed] Using serde instead of rustc_serialize
|
- [changed] Using serde instead of rustc_serialize
|
||||||
|
- [changed] Updated libsodium to 1.0.16
|
||||||
- [changed] Updated dependencies
|
- [changed] Updated dependencies
|
||||||
|
- [changed] Making clippy happy
|
||||||
- [fixed] Fixed wrong address
|
- [fixed] Fixed wrong address
|
||||||
|
|
||||||
### v0.8.1 (2017-05-09)
|
### v0.8.1 (2017-05-09)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
22
Cargo.toml
22
Cargo.toml
|
@ -12,25 +12,25 @@ readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
docopt = "0.8"
|
docopt = "^1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_yaml = "0.7"
|
serde_yaml = "0.8"
|
||||||
log = "0.3"
|
log = { version = "0.4", features = ["std"] }
|
||||||
signal = "0.3"
|
signal = "0.6"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
aligned_alloc = "0.1"
|
aligned_alloc = "0.1"
|
||||||
rand = "0.3"
|
rand = "0.6"
|
||||||
fnv = "1"
|
fnv = "1"
|
||||||
net2 = "0.2"
|
net2 = "0.2"
|
||||||
bitflags = "0.8"
|
bitflags = "^1"
|
||||||
yaml-rust = "0.3"
|
yaml-rust = "0.4"
|
||||||
igd = "0.6"
|
igd = "0.7"
|
||||||
siphasher = "0.2"
|
siphasher = "0.3"
|
||||||
daemonize = "0.2"
|
daemonize = "0.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
cc = "^1"
|
||||||
pkg-config = "0.3"
|
pkg-config = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
4
build.rs
4
build.rs
|
@ -2,7 +2,7 @@
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2017 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
extern crate gcc;
|
extern crate cc;
|
||||||
extern crate pkg_config;
|
extern crate pkg_config;
|
||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -11,7 +11,7 @@ use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
gcc::Config::new().file("src/c/tuntap.c").include("src").compile("libtuntap.a");
|
cc::Build::new().file("src/c/tuntap.c").include("src").compile("libtuntap.a");
|
||||||
if cfg!(feature = "system-libsodium") {
|
if cfg!(feature = "system-libsodium") {
|
||||||
pkg_config::Config::new().atleast_version("1.0.8").probe("libsodium").expect("Libsodium >= 1.0.8 missing");
|
pkg_config::Config::new().atleast_version("1.0.8").probe("libsodium").expect("Libsodium >= 1.0.8 missing");
|
||||||
return
|
return
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 70170c28c844a4786e75efc626e1aeebc93caebc
|
Subproject commit 675149b9b8b66ff44152553fb3ebf9858128363d
|
|
@ -17,7 +17,7 @@ use super::ethernet::{Frame, SwitchTable};
|
||||||
use super::types::{Address, Table, Protocol};
|
use super::types::{Address, Table, Protocol};
|
||||||
use super::ip::Packet;
|
use super::ip::Packet;
|
||||||
use super::util::now as util_now;
|
use super::util::now as util_now;
|
||||||
use super::poll::{self, Poll};
|
use super::poll::{Poll, Flags};
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn crypto_salsa20(b: &mut Bencher) {
|
fn crypto_salsa20(b: &mut Bencher) {
|
||||||
|
@ -141,7 +141,7 @@ fn epoll_wait(b: &mut Bencher) {
|
||||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||||
let mut poll_handle = Poll::new(1).unwrap();
|
let mut poll_handle = Poll::new(1).unwrap();
|
||||||
let fd = socket.as_raw_fd();
|
let fd = socket.as_raw_fd();
|
||||||
poll_handle.register(fd, poll::WRITE).unwrap();
|
poll_handle.register(fd, Flags::WRITE).unwrap();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert_eq!(poll_handle.wait(1000).unwrap().len(), 1)
|
assert_eq!(poll_handle.wait(1000).unwrap().len(), 1)
|
||||||
});
|
});
|
||||||
|
|
53
src/cloud.rs
53
src/cloud.rs
|
@ -14,9 +14,8 @@ use std::time::Instant;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
use libc::{SIGTERM, SIGQUIT, SIGINT};
|
use signal::{trap::Trap, Signal};
|
||||||
use signal::trap::Trap;
|
use rand::{prelude::*, random, thread_rng};
|
||||||
use rand::{random, sample, thread_rng};
|
|
||||||
use net2::UdpBuilder;
|
use net2::UdpBuilder;
|
||||||
|
|
||||||
use super::types::{Table, Protocol, Range, Error, HeaderMagic, NodeId};
|
use super::types::{Table, Protocol, Range, Error, HeaderMagic, NodeId};
|
||||||
|
@ -25,7 +24,7 @@ use super::udpmessage::{encode, decode, Message};
|
||||||
use super::crypto::Crypto;
|
use super::crypto::Crypto;
|
||||||
use super::port_forwarding::PortForwarding;
|
use super::port_forwarding::PortForwarding;
|
||||||
use super::util::{now, Time, Duration, resolve};
|
use super::util::{now, Time, Duration, resolve};
|
||||||
use super::poll::{self, Poll};
|
use super::poll::{Poll, Flags};
|
||||||
|
|
||||||
type Hash = BuildHasherDefault<FnvHasher>;
|
type Hash = BuildHasherDefault<FnvHasher>;
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ impl PeerList {
|
||||||
fn new(timeout: Duration) -> PeerList {
|
fn new(timeout: Duration) -> PeerList {
|
||||||
PeerList{
|
PeerList{
|
||||||
peers: HashMap::default(),
|
peers: HashMap::default(),
|
||||||
timeout: timeout,
|
timeout,
|
||||||
nodes: HashMap::default(),
|
nodes: HashMap::default(),
|
||||||
addresses: HashSet::default()
|
addresses: HashSet::default()
|
||||||
}
|
}
|
||||||
|
@ -96,7 +95,7 @@ impl PeerList {
|
||||||
fn add(&mut self, node_id: NodeId, addr: SocketAddr) {
|
fn add(&mut self, node_id: NodeId, addr: SocketAddr) {
|
||||||
if self.nodes.insert(node_id, addr).is_none() {
|
if self.nodes.insert(node_id, addr).is_none() {
|
||||||
info!("New peer: {}", addr);
|
info!("New peer: {}", addr);
|
||||||
self.peers.insert(addr, (now()+self.timeout as Time, node_id, vec![]));
|
self.peers.insert(addr, (now()+Time::from(self.timeout), node_id, vec![]));
|
||||||
self.addresses.insert(addr);
|
self.addresses.insert(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +103,7 @@ impl PeerList {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn refresh(&mut self, addr: &SocketAddr) {
|
fn refresh(&mut self, addr: &SocketAddr) {
|
||||||
if let Some(&mut (ref mut timeout, _node_id, ref _alt_addrs)) = self.peers.get_mut(addr) {
|
if let Some(&mut (ref mut timeout, _node_id, ref _alt_addrs)) = self.peers.get_mut(addr) {
|
||||||
*timeout = now()+self.timeout as Time;
|
*timeout = now()+Time::from(self.timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +139,7 @@ impl PeerList {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn subset(&self, size: usize) -> Vec<SocketAddr> {
|
fn subset(&self, size: usize) -> Vec<SocketAddr> {
|
||||||
sample(&mut thread_rng(), self.as_vec(), size)
|
self.addresses.iter().choose_multiple(&mut thread_rng(), size).into_iter().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -190,8 +189,7 @@ pub struct GenericCloud<P: Protocol, T: Table> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::too_many_arguments)]
|
||||||
#[allow(too_many_arguments)]
|
|
||||||
pub fn new(magic: HeaderMagic, device: Device, listen: u16, table: T,
|
pub fn new(magic: HeaderMagic, device: Device, listen: u16, table: T,
|
||||||
peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<Range>,
|
peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<Range>,
|
||||||
crypto: Crypto, port_forwarding: Option<PortForwarding>) -> Self {
|
crypto: Crypto, port_forwarding: Option<PortForwarding>) -> Self {
|
||||||
|
@ -207,24 +205,24 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
Err(err) => fail!("Failed to open ipv6 address ::{}: {}", listen, err)
|
Err(err) => fail!("Failed to open ipv6 address ::{}: {}", listen, err)
|
||||||
};
|
};
|
||||||
GenericCloud{
|
GenericCloud{
|
||||||
magic: magic,
|
magic,
|
||||||
node_id: random(),
|
node_id: random(),
|
||||||
peers: PeerList::new(peer_timeout),
|
peers: PeerList::new(peer_timeout),
|
||||||
addresses: addresses,
|
addresses,
|
||||||
learning: learning,
|
learning,
|
||||||
broadcast: broadcast,
|
broadcast,
|
||||||
reconnect_peers: Vec::new(),
|
reconnect_peers: Vec::new(),
|
||||||
blacklist_peers: Vec::new(),
|
blacklist_peers: Vec::new(),
|
||||||
table: table,
|
table,
|
||||||
socket4: socket4,
|
socket4,
|
||||||
socket6: socket6,
|
socket6,
|
||||||
device: device,
|
device,
|
||||||
crypto: crypto,
|
crypto,
|
||||||
next_peerlist: now(),
|
next_peerlist: now(),
|
||||||
update_freq: peer_timeout/2-60,
|
update_freq: peer_timeout/2-60,
|
||||||
buffer_out: [0; 64*1024],
|
buffer_out: [0; 64*1024],
|
||||||
next_housekeep: now(),
|
next_housekeep: now(),
|
||||||
port_forwarding: port_forwarding,
|
port_forwarding,
|
||||||
_dummy_p: PhantomData,
|
_dummy_p: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +382,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
let mut msg = Message::Peers(peers);
|
let mut msg = Message::Peers(peers);
|
||||||
try!(self.broadcast_msg(&mut msg));
|
try!(self.broadcast_msg(&mut msg));
|
||||||
// Reschedule for next update
|
// Reschedule for next update
|
||||||
self.next_peerlist = now + self.update_freq as Time;
|
self.next_peerlist = now + Time::from(self.update_freq);
|
||||||
}
|
}
|
||||||
// Connect to those reconnect_peers that are due
|
// Connect to those reconnect_peers that are due
|
||||||
for entry in self.reconnect_peers.clone() {
|
for entry in self.reconnect_peers.clone() {
|
||||||
|
@ -423,7 +421,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
entry.timeout = MAX_RECONNECT_INTERVAL;
|
entry.timeout = MAX_RECONNECT_INTERVAL;
|
||||||
}
|
}
|
||||||
// Schedule next connection attempt
|
// Schedule next connection attempt
|
||||||
entry.next = now + entry.timeout as Time;
|
entry.next = now + Time::from(entry.timeout);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -574,18 +572,17 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
/// `handle_net_message` method. It will also read from the device and call
|
/// `handle_net_message` method. It will also read from the device and call
|
||||||
/// `handle_interface_data` for each packet read.
|
/// `handle_interface_data` for each packet read.
|
||||||
/// Also, this method will call `housekeep` every second.
|
/// Also, this method will call `housekeep` every second.
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::cyclomatic_complexity)]
|
||||||
#[allow(cyclomatic_complexity)]
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let dummy_time = Instant::now();
|
let dummy_time = Instant::now();
|
||||||
let trap = Trap::trap(&[SIGINT, SIGTERM, SIGQUIT]);
|
let trap = Trap::trap(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGQUIT]);
|
||||||
let mut poll_handle = try_fail!(Poll::new(3), "Failed to create poll handle: {}");
|
let mut poll_handle = try_fail!(Poll::new(3), "Failed to create poll handle: {}");
|
||||||
let socket4_fd = self.socket4.as_raw_fd();
|
let socket4_fd = self.socket4.as_raw_fd();
|
||||||
let socket6_fd = self.socket6.as_raw_fd();
|
let socket6_fd = self.socket6.as_raw_fd();
|
||||||
let device_fd = self.device.as_raw_fd();
|
let device_fd = self.device.as_raw_fd();
|
||||||
try_fail!(poll_handle.register(socket4_fd, poll::READ), "Failed to add ipv4 socket to poll handle: {}");
|
try_fail!(poll_handle.register(socket4_fd, Flags::READ), "Failed to add ipv4 socket to poll handle: {}");
|
||||||
try_fail!(poll_handle.register(socket6_fd, poll::READ), "Failed to add ipv6 socket to poll handle: {}");
|
try_fail!(poll_handle.register(socket6_fd, Flags::READ), "Failed to add ipv6 socket to poll handle: {}");
|
||||||
try_fail!(poll_handle.register(device_fd, poll::READ), "Failed to add device to poll handle: {}");
|
try_fail!(poll_handle.register(device_fd, Flags::READ), "Failed to add device to poll handle: {}");
|
||||||
let mut buffer = [0; 64*1024];
|
let mut buffer = [0; 64*1024];
|
||||||
let mut poll_error = false;
|
let mut poll_error = false;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -172,7 +172,7 @@ impl Config {
|
||||||
let mut s = SipHasher24::new();
|
let mut s = SipHasher24::new();
|
||||||
name[6..].hash(&mut s);
|
name[6..].hash(&mut s);
|
||||||
let mut data = [0; 4];
|
let mut data = [0; 4];
|
||||||
Encoder::write_u32((s.finish() & 0xffffffff) as u32, &mut data);
|
Encoder::write_u32((s.finish() & 0xffff_ffff) as u32, &mut data);
|
||||||
data
|
data
|
||||||
} else {
|
} else {
|
||||||
let num = try_fail!(u32::from_str_radix(name, 16), "Failed to parse header magic: {}");
|
let num = try_fail!(u32::from_str_radix(name, 16), "Failed to parse header magic: {}");
|
||||||
|
|
|
@ -38,9 +38,9 @@ const crypto_pwhash_scryptsalsa208sha256_SALTBYTES: usize = 32;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const crypto_pwhash_scryptsalsa208sha256_STRBYTES: usize = 102;
|
const crypto_pwhash_scryptsalsa208sha256_STRBYTES: usize = 102;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: usize = 524288;
|
const crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE: usize = 524_288;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16777216;
|
const crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE: usize = 16_777_216;
|
||||||
|
|
||||||
pub struct Aes256State(*mut [u8; crypto_aead_aes256gcm_STATEBYTES]);
|
pub struct Aes256State(*mut [u8; crypto_aead_aes256gcm_STATEBYTES]);
|
||||||
|
|
||||||
|
@ -193,8 +193,7 @@ impl Crypto {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::match_same_arms)]
|
||||||
#[allow(match_same_arms)]
|
|
||||||
pub fn additional_bytes(&self) -> usize {
|
pub fn additional_bytes(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
Crypto::None => 0,
|
Crypto::None => 0,
|
||||||
|
@ -225,7 +224,7 @@ impl Crypto {
|
||||||
crypto_key.clone_from_slice(&key[..crypto_aead_chacha20poly1305_ietf_KEYBYTES]);
|
crypto_key.clone_from_slice(&key[..crypto_aead_chacha20poly1305_ietf_KEYBYTES]);
|
||||||
let mut nonce = [0u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES];
|
let mut nonce = [0u8; crypto_aead_chacha20poly1305_ietf_NPUBBYTES];
|
||||||
unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) };
|
unsafe { randombytes_buf(nonce.as_mut_ptr(), nonce.len()) };
|
||||||
Crypto::ChaCha20Poly1305{key: crypto_key, nonce: nonce}
|
Crypto::ChaCha20Poly1305{key: crypto_key, nonce}
|
||||||
},
|
},
|
||||||
CryptoMethod::AES256 => {
|
CryptoMethod::AES256 => {
|
||||||
if ! Crypto::aes256_available() {
|
if ! Crypto::aes256_available() {
|
||||||
|
@ -239,7 +238,7 @@ impl Crypto {
|
||||||
key[..crypto_aead_aes256gcm_KEYBYTES].as_ptr() as *const [u8; crypto_aead_aes256gcm_KEYBYTES]
|
key[..crypto_aead_aes256gcm_KEYBYTES].as_ptr() as *const [u8; crypto_aead_aes256gcm_KEYBYTES]
|
||||||
) };
|
) };
|
||||||
assert_eq!(res, 0);
|
assert_eq!(res, 0);
|
||||||
Crypto::AES256GCM{state: state, nonce: nonce}
|
Crypto::AES256GCM{state, nonce}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl Device {
|
||||||
while ifname_c.last() == Some(&0) {
|
while ifname_c.last() == Some(&0) {
|
||||||
ifname_c.pop();
|
ifname_c.pop();
|
||||||
}
|
}
|
||||||
Ok(Device{fd: fd, ifname: String::from_utf8(ifname_c).unwrap(), type_: type_})
|
Ok(Device{fd, ifname: String::from_utf8(ifname_c).unwrap(), type_})
|
||||||
},
|
},
|
||||||
_ => Err(IoError::last_os_error())
|
_ => Err(IoError::last_os_error())
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ impl Device {
|
||||||
Ok(Device{
|
Ok(Device{
|
||||||
fd: try!(fs::OpenOptions::new().create(true).read(true).write(true).open(path)),
|
fd: try!(fs::OpenOptions::new().create(true).read(true).write(true).open(path)),
|
||||||
ifname: ifname.to_string(),
|
ifname: ifname.to_string(),
|
||||||
type_: type_
|
type_
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub struct SwitchTable {
|
||||||
impl SwitchTable {
|
impl SwitchTable {
|
||||||
/// Creates a new switch table
|
/// Creates a new switch table
|
||||||
pub fn new(timeout: Duration, protection_period: Duration) -> Self {
|
pub fn new(timeout: Duration, protection_period: Duration) -> Self {
|
||||||
SwitchTable{table: HashMap::default(), timeout: timeout, protection_period: protection_period}
|
SwitchTable{table: HashMap::default(), timeout, protection_period}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ impl Table for SwitchTable {
|
||||||
/// Learns the given address, inserting it in the hash map
|
/// Learns the given address, inserting it in the hash map
|
||||||
#[inline]
|
#[inline]
|
||||||
fn learn(&mut self, key: Address, _prefix_len: Option<u8>, addr: SocketAddr) {
|
fn learn(&mut self, key: Address, _prefix_len: Option<u8>, addr: SocketAddr) {
|
||||||
let deadline = now() + self.timeout as Time;
|
let deadline = now() + Time::from(self.timeout);
|
||||||
match self.table.entry(key) {
|
match self.table.entry(key) {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
entry.insert(SwitchTableValue{address: addr, timeout: deadline});
|
entry.insert(SwitchTableValue{address: addr, timeout: deadline});
|
||||||
|
@ -110,7 +110,7 @@ impl Table for SwitchTable {
|
||||||
},
|
},
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
let mut entry = entry.get_mut();
|
let mut entry = entry.get_mut();
|
||||||
if entry.timeout + self.protection_period as Time > deadline {
|
if entry.timeout + Time::from(self.protection_period) > deadline {
|
||||||
// Do not override recently learnt entries
|
// Do not override recently learnt entries
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
10
src/ip.rs
10
src/ip.rs
|
@ -24,7 +24,7 @@ impl Protocol for Packet {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// This method will fail when the given data is not a valid ipv4 and ipv6 packet.
|
/// This method will fail when the given data is not a valid ipv4 and ipv6 packet.
|
||||||
fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
|
fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
|
||||||
if data.len() < 1 {
|
if data.is_empty() {
|
||||||
return Err(Error::Parse("Empty header"));
|
return Err(Error::Parse("Empty header"));
|
||||||
}
|
}
|
||||||
let version = data[0] >> 4;
|
let version = data[0] >> 4;
|
||||||
|
@ -90,16 +90,16 @@ impl Table for RoutingTable {
|
||||||
let mut group_bytes = [0; 16];
|
let mut group_bytes = [0; 16];
|
||||||
group_bytes[..group_len].copy_from_slice(&addr.data[..group_len]);
|
group_bytes[..group_len].copy_from_slice(&addr.data[..group_len]);
|
||||||
// Create an entry
|
// Create an entry
|
||||||
let routing_entry = RoutingEntry{address: address, bytes: addr.data, prefix_len: prefix_len};
|
let routing_entry = RoutingEntry{address, bytes: addr.data, prefix_len};
|
||||||
// Add the entry to the routing table, creating a new list of the prefix group is empty.
|
// Add the entry to the routing table, creating a new list of the prefix group is empty.
|
||||||
match self.0.entry(group_bytes) {
|
match self.0.entry(group_bytes) {
|
||||||
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
|
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
|
||||||
hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () }
|
hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a peer for an address if it is inside the routing table
|
/// Retrieves a peer for an address if it is inside the routing table
|
||||||
#[allow(unknown_lints, needless_range_loop)]
|
#[allow(unknown_lints, clippy::needless_range_loop)]
|
||||||
fn lookup(&mut self, addr: &Address) -> Option<SocketAddr> {
|
fn lookup(&mut self, addr: &Address) -> Option<SocketAddr> {
|
||||||
let len = addr.len as usize;
|
let len = addr.len as usize;
|
||||||
let mut found = None;
|
let mut found = None;
|
||||||
|
@ -110,7 +110,7 @@ impl Table for RoutingTable {
|
||||||
for i in len..16 {
|
for i in len..16 {
|
||||||
group_bytes[i] = 0;
|
group_bytes[i] = 0;
|
||||||
}
|
}
|
||||||
for i in (0..len+1).rev() {
|
for i in (0..=len).rev() {
|
||||||
if i < len {
|
if i < len {
|
||||||
group_bytes[i] = 0;
|
group_bytes[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
35
src/main.rs
35
src/main.rs
|
@ -62,6 +62,7 @@ const MAGIC: HeaderMagic = *b"vpn\x01";
|
||||||
|
|
||||||
static USAGE: &'static str = include_str!("usage.txt");
|
static USAGE: &'static str = include_str!("usage.txt");
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Default)]
|
#[derive(Deserialize, Debug, Default)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
flag_config: Option<String>,
|
flag_config: Option<String>,
|
||||||
|
@ -90,7 +91,6 @@ pub struct Args {
|
||||||
flag_log_file: Option<String>
|
flag_log_file: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct DualLogger {
|
struct DualLogger {
|
||||||
file: Mutex<Option<File>>
|
file: Mutex<Option<File>>
|
||||||
}
|
}
|
||||||
|
@ -108,12 +108,12 @@ impl DualLogger {
|
||||||
|
|
||||||
impl log::Log for DualLogger {
|
impl log::Log for DualLogger {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn enabled(&self, _metadata: &log::LogMetadata) -> bool {
|
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn log(&self, record: &log::LogRecord) {
|
fn log(&self, record: &log::Record) {
|
||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
println!("{} - {}", record.level(), record.args());
|
println!("{} - {}", record.level(), record.args());
|
||||||
let mut file = self.file.lock().expect("Lock poisoned");
|
let mut file = self.file.lock().expect("Lock poisoned");
|
||||||
|
@ -123,6 +123,14 @@ impl log::Log for DualLogger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn flush(&self) {
|
||||||
|
let mut file = self.file.lock().expect("Lock poisoned");
|
||||||
|
if let Some(ref mut file) = *file {
|
||||||
|
try_fail!(file.flush(), "Logging error: {}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_script(script: &str, ifname: &str) {
|
fn run_script(script: &str, ifname: &str) {
|
||||||
|
@ -130,9 +138,7 @@ fn run_script(script: &str, ifname: &str) {
|
||||||
cmd.arg("-c").arg(&script).env("IFNAME", ifname);
|
cmd.arg("-c").arg(&script).env("IFNAME", ifname);
|
||||||
debug!("Running script: {:?}", cmd);
|
debug!("Running script: {:?}", cmd);
|
||||||
match cmd.status() {
|
match cmd.status() {
|
||||||
Ok(status) => if status.success() {
|
Ok(status) => if !status.success() {
|
||||||
()
|
|
||||||
} else {
|
|
||||||
error!("Script returned with error: {:?}", status.code())
|
error!("Script returned with error: {:?}", status.code())
|
||||||
},
|
},
|
||||||
Err(e) => error!("Failed to execute script {:?}: {}", script, e)
|
Err(e) => error!("Failed to execute script {:?}: {}", script, e)
|
||||||
|
@ -150,7 +156,7 @@ enum AnyCloud<P: Protocol> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Protocol> AnyCloud<P> {
|
impl<P: Protocol> AnyCloud<P> {
|
||||||
#[allow(unknown_lints,too_many_arguments)]
|
#[allow(unknown_lints,clippy::too_many_arguments)]
|
||||||
fn new(magic: HeaderMagic, device: Device, listen: u16, table: AnyTable,
|
fn new(magic: HeaderMagic, device: Device, listen: u16, table: AnyTable,
|
||||||
peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<Range>,
|
peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<Range>,
|
||||||
crypto: Crypto, port_forwarding: Option<PortForwarding>) -> Self {
|
crypto: Crypto, port_forwarding: Option<PortForwarding>) -> Self {
|
||||||
|
@ -264,17 +270,18 @@ fn main() {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log::set_logger(|max_log_level| {
|
let logger = try_fail!(DualLogger::new(args.flag_log_file.as_ref()), "Failed to open logfile: {}");
|
||||||
assert!(!args.flag_verbose || !args.flag_quiet);
|
log::set_boxed_logger(Box::new(logger)).unwrap();
|
||||||
|
assert!(!args.flag_verbose || !args.flag_quiet);
|
||||||
|
log::set_max_level(
|
||||||
if args.flag_verbose {
|
if args.flag_verbose {
|
||||||
max_log_level.set(log::LogLevelFilter::Debug);
|
log::LevelFilter::Debug
|
||||||
} else if args.flag_quiet {
|
} else if args.flag_quiet {
|
||||||
max_log_level.set(log::LogLevelFilter::Error);
|
log::LevelFilter::Error
|
||||||
} else {
|
} else {
|
||||||
max_log_level.set(log::LogLevelFilter::Info);
|
log::LevelFilter::Info
|
||||||
}
|
}
|
||||||
Box::new(try_fail!(DualLogger::new(args.flag_log_file.as_ref()), "Failed to open logfile: {}"))
|
);
|
||||||
}).unwrap();
|
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
if let Some(ref file) = args.flag_config {
|
if let Some(ref file) = args.flag_config {
|
||||||
info!("Reading config file '{}'", file);
|
info!("Reading config file '{}'", file);
|
||||||
|
|
|
@ -9,10 +9,10 @@ use std::io;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
bitflags!{
|
bitflags!{
|
||||||
pub flags Flags: u32 {
|
pub struct Flags: u32 {
|
||||||
const READ = libc::EPOLLIN as u32,
|
const READ = libc::EPOLLIN as u32;
|
||||||
const WRITE = libc::EPOLLOUT as u32,
|
const WRITE = libc::EPOLLOUT as u32;
|
||||||
const ERROR = libc::EPOLLERR as u32,
|
const ERROR = libc::EPOLLERR as u32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ impl Poll {
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
return Err(io::Error::last_os_error());
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
Ok(Poll{fd: fd, events: events})
|
Ok(Poll{fd, events})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -10,7 +10,7 @@ use igd::*;
|
||||||
use super::util::{Time, now};
|
use super::util::{Time, now};
|
||||||
|
|
||||||
const LEASE_TIME: u32 = 300;
|
const LEASE_TIME: u32 = 300;
|
||||||
const DESCRIPTION: &'static str = "VpnCloud";
|
const DESCRIPTION: &str = "VpnCloud";
|
||||||
|
|
||||||
|
|
||||||
pub struct PortForwarding {
|
pub struct PortForwarding {
|
||||||
|
@ -90,15 +90,15 @@ impl PortForwarding {
|
||||||
};
|
};
|
||||||
info!("Port-forwarding: sucessfully activated port forward on {}, timeout: {}", external_addr, timeout);
|
info!("Port-forwarding: sucessfully activated port forward on {}, timeout: {}", external_addr, timeout);
|
||||||
let next_extension = if timeout > 0 {
|
let next_extension = if timeout > 0 {
|
||||||
Some(now() + timeout as Time - 60)
|
Some(now() + Time::from(timeout) - 60)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Some(PortForwarding {
|
Some(PortForwarding {
|
||||||
internal_addr: internal_addr,
|
internal_addr,
|
||||||
external_addr: external_addr,
|
external_addr,
|
||||||
gateway: gateway,
|
gateway,
|
||||||
next_extension: next_extension
|
next_extension
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ impl PortForwarding {
|
||||||
Ok(()) => debug!("Port-forwarding: extended port forwarding"),
|
Ok(()) => debug!("Port-forwarding: extended port forwarding"),
|
||||||
Err(err) => error!("Port-forwarding: failed to extend port forwarding: {}", err)
|
Err(err) => error!("Port-forwarding: failed to extend port forwarding: {}", err)
|
||||||
};
|
};
|
||||||
self.next_extension = Some(now() + LEASE_TIME as Time - 60);
|
self.next_extension = Some(now() + Time::from(LEASE_TIME) - 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate(&self) {
|
fn deactivate(&self) {
|
||||||
|
|
15
src/types.rs
15
src/types.rs
|
@ -25,7 +25,7 @@ pub struct Address {
|
||||||
impl Address {
|
impl Address {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_from(data: &[u8]) -> Result<(Address, usize), Error> {
|
pub fn read_from(data: &[u8]) -> Result<(Address, usize), Error> {
|
||||||
if data.len() < 1 {
|
if data.is_empty() {
|
||||||
return Err(Error::Parse("Address too short"));
|
return Err(Error::Parse("Address too short"));
|
||||||
}
|
}
|
||||||
let len = data[0] as usize;
|
let len = data[0] as usize;
|
||||||
|
@ -48,10 +48,10 @@ impl Address {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_to(&self, data: &mut[u8]) -> usize {
|
pub fn write_to(&self, data: &mut[u8]) -> usize {
|
||||||
assert!(data.len() >= self.len as usize + 1);
|
assert!(data.len() > self.len as usize);
|
||||||
data[0] = self.len;
|
data[0] = self.len;
|
||||||
let len = self.len as usize;
|
let len = self.len as usize;
|
||||||
data[1..len+1].copy_from_slice(&self.data[0..len]);
|
data[1..=len].copy_from_slice(&self.data[0..len]);
|
||||||
self.len as usize + 1
|
self.len as usize + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,7 @@ impl fmt::Debug for Address {
|
||||||
impl FromStr for Address {
|
impl FromStr for Address {
|
||||||
type Err=Error;
|
type Err=Error;
|
||||||
|
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::needless_range_loop)]
|
||||||
#[allow(needless_range_loop)]
|
|
||||||
fn from_str(text: &str) -> Result<Self, Self::Err> {
|
fn from_str(text: &str) -> Result<Self, Self::Err> {
|
||||||
if let Ok(addr) = Ipv4Addr::from_str(text) {
|
if let Ok(addr) = Ipv4Addr::from_str(text) {
|
||||||
let ip = addr.octets();
|
let ip = addr.octets();
|
||||||
|
@ -145,13 +144,13 @@ impl Range {
|
||||||
return Err(Error::Parse("Range too short"));
|
return Err(Error::Parse("Range too short"));
|
||||||
}
|
}
|
||||||
let prefix_len = data[read];
|
let prefix_len = data[read];
|
||||||
Ok((Range{base: address, prefix_len: prefix_len}, read + 1))
|
Ok((Range{base: address, prefix_len}, read + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn write_to(&self, data: &mut[u8]) -> usize {
|
pub fn write_to(&self, data: &mut[u8]) -> usize {
|
||||||
let pos = self.base.write_to(data);
|
let pos = self.base.write_to(data);
|
||||||
assert!(data.len() >= pos + 1);
|
assert!(data.len() > pos);
|
||||||
data[pos] = self.prefix_len;
|
data[pos] = self.prefix_len;
|
||||||
pos + 1
|
pos + 1
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,7 @@ impl FromStr for Range {
|
||||||
let prefix_len = try!(u8::from_str(&text[pos+1..])
|
let prefix_len = try!(u8::from_str(&text[pos+1..])
|
||||||
.map_err(|_| Error::Parse("Failed to parse prefix length")));
|
.map_err(|_| Error::Parse("Failed to parse prefix length")));
|
||||||
let base = try!(Address::from_str(&text[..pos]));
|
let base = try!(Address::from_str(&text[..pos]));
|
||||||
Ok(Range{base: base, prefix_len: prefix_len})
|
Ok(Range{base, prefix_len})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ impl TopHeader {
|
||||||
Ok((header, TopHeader::size()))
|
Ok((header, TopHeader::size()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unknown_lints,clippy::trivially_copy_pass_by_ref)]
|
||||||
pub fn write_to(&self, data: &mut [u8]) -> usize {
|
pub fn write_to(&self, data: &mut [u8]) -> usize {
|
||||||
assert!(data.len() >= 8);
|
assert!(data.len() >= 8);
|
||||||
data[0..4].copy_from_slice(&self.magic);
|
data[0..4].copy_from_slice(&self.magic);
|
||||||
|
@ -76,8 +77,7 @@ impl<'a> fmt::Debug for Message<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::needless_range_loop)]
|
||||||
#[allow(needless_range_loop)]
|
|
||||||
pub fn decode<'a>(data: &'a mut [u8], magic: HeaderMagic, crypto: &mut Crypto) -> Result<Message<'a>, Error> {
|
pub fn decode<'a>(data: &'a mut [u8], magic: HeaderMagic, crypto: &mut Crypto) -> Result<Message<'a>, Error> {
|
||||||
let mut end = data.len();
|
let mut end = data.len();
|
||||||
let (header, mut pos) = try!(TopHeader::read_from(&data[..end]));
|
let (header, mut pos) = try!(TopHeader::read_from(&data[..end]));
|
||||||
|
@ -170,8 +170,7 @@ pub fn decode<'a>(data: &'a mut [u8], magic: HeaderMagic, crypto: &mut Crypto) -
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unknown_lints)]
|
#[allow(unknown_lints,clippy::needless_range_loop)]
|
||||||
#[allow(needless_range_loop)]
|
|
||||||
pub fn encode<'a>(msg: &'a mut Message, mut buf: &'a mut [u8], magic: HeaderMagic, crypto: &mut Crypto) -> &'a mut [u8] {
|
pub fn encode<'a>(msg: &'a mut Message, mut buf: &'a mut [u8], magic: HeaderMagic, crypto: &mut Crypto) -> &'a mut [u8] {
|
||||||
let mut start = 64;
|
let mut start = 64;
|
||||||
let mut end = 64;
|
let mut end = 64;
|
||||||
|
|
18
src/util.rs
18
src/util.rs
|
@ -30,7 +30,7 @@ pub fn now() -> Time {
|
||||||
time::get_time().sec
|
time::get_time().sec
|
||||||
}
|
}
|
||||||
|
|
||||||
const HEX_CHARS: &'static [u8] = b"0123456789abcdef";
|
const HEX_CHARS: &[u8] = b"0123456789abcdef";
|
||||||
|
|
||||||
pub fn bytes_to_hex(bytes: &[u8]) -> String {
|
pub fn bytes_to_hex(bytes: &[u8]) -> String {
|
||||||
let mut v = Vec::with_capacity(bytes.len() * 2);
|
let mut v = Vec::with_capacity(bytes.len() * 2);
|
||||||
|
@ -49,7 +49,7 @@ pub struct Encoder;
|
||||||
impl Encoder {
|
impl Encoder {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_u16(data: &[u8]) -> u16 {
|
pub fn read_u16(data: &[u8]) -> u16 {
|
||||||
((data[0] as u16) << 8) | data[1] as u16
|
(u16::from(data[0]) << 8) | u16::from(data[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -60,8 +60,8 @@ impl Encoder {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_u32(data: &[u8]) -> u32 {
|
pub fn read_u32(data: &[u8]) -> u32 {
|
||||||
((data[0] as u32) << 24) | ((data[1] as u32) << 16) |
|
(u32::from(data[0]) << 24) | (u32::from(data[1]) << 16) |
|
||||||
((data[2] as u32) << 8) | data[3] as u32
|
(u32::from(data[2]) << 8) | u32::from(data[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -74,10 +74,10 @@ impl Encoder {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_u64(data: &[u8]) -> u64 {
|
pub fn read_u64(data: &[u8]) -> u64 {
|
||||||
((data[0] as u64) << 56) | ((data[1] as u64) << 48) |
|
(u64::from(data[0]) << 56) | (u64::from(data[1]) << 48) |
|
||||||
((data[2] as u64) << 40) | ((data[3] as u64) << 32) |
|
(u64::from(data[2]) << 40) | (u64::from(data[3]) << 32) |
|
||||||
((data[4] as u64) << 24) | ((data[5] as u64) << 16) |
|
(u64::from(data[4]) << 24) | (u64::from(data[5]) << 16) |
|
||||||
((data[6] as u64) << 8) | data[7] as u64
|
(u64::from(data[6]) << 8) | u64::from(data[7])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -123,7 +123,7 @@ macro_rules! try_fail {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(unknown_lints,needless_pass_by_value)]
|
#[allow(unknown_lints,clippy::needless_pass_by_value)]
|
||||||
pub fn resolve<Addr: ToSocketAddrs+fmt::Debug>(addr: Addr) -> Result<Vec<SocketAddr>, Error> {
|
pub fn resolve<Addr: ToSocketAddrs+fmt::Debug>(addr: Addr) -> Result<Vec<SocketAddr>, Error> {
|
||||||
let addrs = try!(addr.to_socket_addrs().map_err(|_| Error::Name(format!("{:?}", addr))));
|
let addrs = try!(addr.to_socket_addrs().map_err(|_| Error::Name(format!("{:?}", addr))));
|
||||||
// Remove duplicates in addrs (why are there duplicates???)
|
// Remove duplicates in addrs (why are there duplicates???)
|
||||||
|
|
Loading…
Reference in New Issue