vpncloud/src/main.rs

134 lines
4.6 KiB
Rust
Raw Normal View History

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-23 00:04:30 +00:00
mod types;
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-23 00:40:47 +00:00
use std::str::FromStr;
2015-11-20 17:40:23 +00:00
2015-11-23 00:40:47 +00:00
use device::Device;
use ethernet::SwitchTable;
use ip::RoutingTable;
use types::{Error, Behavior, Type, Range, Table};
2015-11-23 00:04:30 +00:00
use cloud::{TapCloud, TunCloud};
2015-11-19 15:34:20 +00:00
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-23 00:40:47 +00:00
--subnet <subnet>... The local subnets to use
--dst-timeout <dst_timeout> Switch table entry timeout in seconds [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
";
#[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,
2015-11-23 00:40:47 +00:00
flag_dst_timeout: usize,
2015-11-19 16:23:36 +00:00
flag_verbose: bool,
flag_quiet: bool
2015-11-19 15:34:20 +00:00
}
2015-11-22 19:02:02 +00:00
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);
2015-11-23 00:40:47 +00:00
let device = Device::new(&args.flag_device, args.flag_type).expect("Failed to open virtual interface");
info!("Opened device {}", device.ifname());
let mut ranges = Vec::with_capacity(args.flag_subnet.len());
for s in args.flag_subnet {
ranges.push(Range::from_str(&s).expect("Invalid subnet"));
2015-11-22 19:02:02 +00:00
}
2015-11-23 00:40:47 +00:00
let dst_timeout = Duration::seconds(args.flag_dst_timeout as i64);
let peer_timeout = Duration::seconds(args.flag_peer_timeout as i64);
let (learning, broadcasting, table): (bool, bool, Box<Table>) = match args.flag_behavior {
Behavior::Normal => match args.flag_type {
Type::Tap => (true, true, Box::new(SwitchTable::new(dst_timeout))),
Type::Tun => (false, false, Box::new(RoutingTable::new()))
},
Behavior::Router => (false, false, Box::new(RoutingTable::new())),
Behavior::Switch => (true, true, Box::new(SwitchTable::new(dst_timeout))),
Behavior::Hub => (false, true, Box::new(SwitchTable::new(dst_timeout)))
};
let network_id = args.flag_network_id.map(|name| {
let mut s = SipHasher::new();
name.hash(&mut s);
s.finish()
});
match args.flag_type {
Type::Tap => {
let mut cloud = TapCloud::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges);
for addr in args.flag_connect {
cloud.connect(&addr as &str, true).expect("Failed to send");
}
cloud.run()
},
Type::Tun => {
let mut cloud = TunCloud::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges);
for addr in args.flag_connect {
cloud.connect(&addr as &str, true).expect("Failed to send");
}
cloud.run()
}
};
2015-11-22 19:02:02 +00:00
}