2015-11-19 15:34:20 +00:00
|
|
|
#[macro_use] extern crate log;
|
|
|
|
extern crate time;
|
|
|
|
extern crate docopt;
|
|
|
|
extern crate rustc_serialize;
|
2015-11-20 08:11:54 +00:00
|
|
|
extern crate epoll;
|
2015-11-19 15:34:20 +00:00
|
|
|
|
2015-11-19 18:29:42 +00:00
|
|
|
mod util;
|
2015-11-19 15:34:20 +00:00
|
|
|
mod udpmessage;
|
|
|
|
mod ethernet;
|
2015-11-21 15:50:50 +00:00
|
|
|
mod ip;
|
2015-11-22 16:28:04 +00:00
|
|
|
mod cloud;
|
2015-11-22 18:00:56 +00:00
|
|
|
mod device;
|
2015-11-19 15:34:20 +00:00
|
|
|
|
|
|
|
use time::Duration;
|
|
|
|
use docopt::Docopt;
|
|
|
|
|
2015-11-20 17:40:23 +00:00
|
|
|
use std::hash::{Hash, SipHasher, Hasher};
|
|
|
|
|
2015-11-22 22:34:54 +00:00
|
|
|
use cloud::{Error, TapCloud, TunCloud, Behavior};
|
2015-11-19 15:34:20 +00:00
|
|
|
|
|
|
|
|
2015-11-22 22:34:54 +00:00
|
|
|
//TODO: hub behavior
|
|
|
|
//TODO: L2 routing/L3 switching
|
2015-11-19 18:29:42 +00:00
|
|
|
//TODO: Implement IPv6
|
2015-11-19 19:51:53 +00:00
|
|
|
//TODO: Encryption
|
|
|
|
//TODO: Call close
|
2015-11-19 18:29:42 +00:00
|
|
|
|
2015-11-19 15:34:20 +00:00
|
|
|
|
|
|
|
struct SimpleLogger;
|
|
|
|
|
|
|
|
impl log::Log for SimpleLogger {
|
|
|
|
fn enabled(&self, _metadata: &log::LogMetadata) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn log(&self, record: &log::LogRecord) {
|
|
|
|
if self.enabled(record.metadata()) {
|
|
|
|
println!("{} - {}", record.level(), record.args());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static USAGE: &'static str = "
|
|
|
|
Usage:
|
2015-11-22 19:02:02 +00:00
|
|
|
ethcloud [options] [-t <type>] [-d <device>] [-l <listen>] [-c <connect>...]
|
2015-11-19 15:34:20 +00:00
|
|
|
|
|
|
|
Options:
|
2015-11-22 19:02:02 +00:00
|
|
|
-t <type>, --type <type> Set the type of network [default: tap]
|
2015-11-22 22:34:54 +00:00
|
|
|
--behavior <behavior> The behavior of the vpn [default: normal]
|
2015-11-22 19:02:02 +00:00
|
|
|
-d <device>, --device <device> Name of the virtual device [default: cloud%d]
|
2015-11-19 16:23:36 +00:00
|
|
|
-l <listen>, --listen <listen> Address to listen on [default: 0.0.0.0:3210]
|
|
|
|
-c <connect>, --connect <connect> List of peers (addr:port) to connect to
|
2015-11-20 17:09:51 +00:00
|
|
|
--network-id <network_id> Optional token that identifies the network
|
2015-11-19 21:45:20 +00:00
|
|
|
--peer-timeout <peer_timeout> Peer timeout in seconds [default: 1800]
|
2015-11-22 22:34:54 +00:00
|
|
|
--subnet <subnet>... The local subnets to use (only for tun)
|
2015-11-22 19:02:02 +00:00
|
|
|
--mac-timeout <mac_timeout> Mac table entry timeout in seconds (only for tap) [default: 300]
|
2015-11-19 16:23:36 +00:00
|
|
|
-v, --verbose Log verbosely
|
|
|
|
-q, --quiet Only print error messages
|
2015-11-20 13:05:35 +00:00
|
|
|
-h, --help Display the help
|
2015-11-19 15:34:20 +00:00
|
|
|
";
|
|
|
|
|
2015-11-22 19:02:02 +00:00
|
|
|
#[derive(RustcDecodable, Debug)]
|
|
|
|
enum Type {
|
|
|
|
Tun, Tap
|
|
|
|
}
|
|
|
|
|
2015-11-19 15:34:20 +00:00
|
|
|
#[derive(RustcDecodable, Debug)]
|
|
|
|
struct Args {
|
2015-11-22 19:02:02 +00:00
|
|
|
flag_type: Type,
|
2015-11-22 22:34:54 +00:00
|
|
|
flag_behavior: Behavior,
|
|
|
|
flag_subnet: Vec<String>,
|
2015-11-19 16:23:36 +00:00
|
|
|
flag_device: String,
|
|
|
|
flag_listen: String,
|
2015-11-20 17:40:23 +00:00
|
|
|
flag_network_id: Option<String>,
|
2015-11-19 16:23:36 +00:00
|
|
|
flag_connect: Vec<String>,
|
|
|
|
flag_peer_timeout: usize,
|
|
|
|
flag_mac_timeout: usize,
|
|
|
|
flag_verbose: bool,
|
|
|
|
flag_quiet: bool
|
2015-11-19 15:34:20 +00:00
|
|
|
}
|
|
|
|
|
2015-11-22 19:02:02 +00:00
|
|
|
fn tap_cloud(args: Args) {
|
2015-11-22 15:48:01 +00:00
|
|
|
let mut tapcloud = TapCloud::new_tap_cloud(
|
2015-11-19 15:34:20 +00:00
|
|
|
&args.flag_device,
|
|
|
|
args.flag_listen,
|
2015-11-22 22:34:54 +00:00
|
|
|
args.flag_behavior,
|
2015-11-20 17:40:23 +00:00
|
|
|
args.flag_network_id.map(|name| {
|
|
|
|
let mut s = SipHasher::new();
|
|
|
|
name.hash(&mut s);
|
|
|
|
s.finish()
|
|
|
|
}),
|
2015-11-19 15:34:20 +00:00
|
|
|
Duration::seconds(args.flag_mac_timeout as i64),
|
|
|
|
Duration::seconds(args.flag_peer_timeout as i64)
|
|
|
|
);
|
|
|
|
for addr in args.flag_connect {
|
2015-11-20 11:09:07 +00:00
|
|
|
tapcloud.connect(&addr as &str, true).expect("Failed to send");
|
2015-11-19 15:34:20 +00:00
|
|
|
}
|
2015-11-19 19:51:53 +00:00
|
|
|
tapcloud.run()
|
2015-11-19 15:34:20 +00:00
|
|
|
}
|
2015-11-22 19:02:02 +00:00
|
|
|
|
|
|
|
fn tun_cloud(args: Args) {
|
|
|
|
let mut tuncloud = TunCloud::new_tun_cloud(
|
|
|
|
&args.flag_device,
|
|
|
|
args.flag_listen,
|
2015-11-22 22:34:54 +00:00
|
|
|
args.flag_behavior,
|
2015-11-22 19:02:02 +00:00
|
|
|
args.flag_network_id.map(|name| {
|
|
|
|
let mut s = SipHasher::new();
|
|
|
|
name.hash(&mut s);
|
|
|
|
s.finish()
|
|
|
|
}),
|
2015-11-22 21:00:34 +00:00
|
|
|
args.flag_subnet,
|
2015-11-22 19:02:02 +00:00
|
|
|
Duration::seconds(args.flag_peer_timeout as i64)
|
|
|
|
);
|
|
|
|
for addr in args.flag_connect {
|
|
|
|
tuncloud.connect(&addr as &str, true).expect("Failed to send");
|
|
|
|
}
|
|
|
|
tuncloud.run()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
|
|
|
|
log::set_logger(|max_log_level| {
|
|
|
|
assert!(!args.flag_verbose || !args.flag_quiet);
|
|
|
|
if args.flag_verbose {
|
|
|
|
max_log_level.set(log::LogLevelFilter::Debug);
|
|
|
|
} else if args.flag_quiet {
|
|
|
|
max_log_level.set(log::LogLevelFilter::Error);
|
|
|
|
} else {
|
|
|
|
max_log_level.set(log::LogLevelFilter::Info);
|
|
|
|
}
|
|
|
|
Box::new(SimpleLogger)
|
|
|
|
}).unwrap();
|
|
|
|
debug!("Args: {:?}", args);
|
|
|
|
match args.flag_type {
|
|
|
|
Type::Tap => tap_cloud(args),
|
|
|
|
Type::Tun => tun_cloud(args)
|
|
|
|
}
|
|
|
|
}
|