diff --git a/src/cloud.rs b/src/cloud.rs index 0a7a624..cf28b96 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -131,6 +131,10 @@ impl GenericCloud

{ } } + pub fn ifname(&self) -> &str { + self.device.ifname() + } + fn send_msg(&mut self, addr: Addr, msg: &Message) -> Result<(), Error> { debug!("Sending {:?} to {}", msg, addr); let size = encode(&mut self.options, msg, &mut self.buffer_out, &mut self.crypto); diff --git a/src/main.rs b/src/main.rs index 3a8d303..4ee58b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ use docopt::Docopt; use std::hash::{Hash, SipHasher, Hasher}; use std::str::FromStr; +use std::process::Command; use device::Device; use ethernet::SwitchTable; @@ -62,7 +63,22 @@ struct Args { flag_peer_timeout: usize, flag_dst_timeout: usize, flag_verbose: bool, - flag_quiet: bool + flag_quiet: bool, + flag_ifup: Option, + flag_ifdown: Option +} + +fn run_script(script: String, ifname: &str) { + let mut cmd = Command::new("sh"); + cmd.arg("-c").arg(&script).env("IFNAME", ifname); + debug!("Running script: {:?}", cmd); + match cmd.status() { + Ok(status) => match status.success() { + true => (), + false => error!("Script returned with error: {:?}", status.code()) + }, + Err(e) => error!("Failed to execute script {:?}: {}", script, e) + } } fn main() { @@ -108,16 +124,28 @@ fn main() { match args.flag_type { Type::Tap => { let mut cloud = TapCloud::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges, crypto); + if let Some(script) = args.flag_ifup { + run_script(script, cloud.ifname()); + } for addr in &args.flag_connect { cloud.connect(&addr as &str, true).expect("Failed to send"); } - cloud.run() + cloud.run(); + if let Some(script) = args.flag_ifdown { + run_script(script, cloud.ifname()); + } }, Type::Tun => { let mut cloud = TunCloud::new(device, args.flag_listen, network_id, table, peer_timeout, learning, broadcasting, ranges, crypto); + if let Some(script) = args.flag_ifup { + run_script(script, cloud.ifname()); + } for addr in &args.flag_connect { cloud.connect(&addr as &str, true).expect("Failed to send"); } + if let Some(script) = args.flag_ifdown { + run_script(script, cloud.ifname()); + } cloud.run() } }; diff --git a/src/usage.txt b/src/usage.txt index 38853b1..b27e95b 100644 --- a/src/usage.txt +++ b/src/usage.txt @@ -17,6 +17,9 @@ Options: --peer-timeout Peer timeout in seconds. [default: 1800] --dst-timeout Switch table entry timeout in seconds. [default: 300] + --ifup A command to setup the network interface. + --ifdown A command to bring down the network + interface. -v, --verbose Print debug information. -q, --quiet Only print errors and warnings. -h, --help Display the help. diff --git a/vpncloud.md b/vpncloud.md index e4b226b..a2676e7 100644 --- a/vpncloud.md +++ b/vpncloud.md @@ -65,6 +65,20 @@ vpncloud(1) -- Peer-to-peer VPN mode. Addresses that have not been seen for the given period of time will be forgot. [default: 300] + * `--ifup `: + + A command to setup the network interface. The command will be run (as + parameter to `sh -c`) when the device has been created to configure it. + The name of the allocated device will be available via the environment + variable `IFNAME`. + + * `--ifdown `: + + A command to bring down the network interface. The command will be run (as + parameter to `sh -c`) to remove any configuration from the device. + The name of the allocated device will be available via the environment + variable `IFNAME`. + * `-v`, `--verbose`: Print debug information, including information for data being received and @@ -138,15 +152,10 @@ In the example scenario, a simple layer 2 network tunnel is established. Most likely those commands need to be run as **root** using `sudo`. First, VpnCloud need to be started on both nodes (the address after `-c` is the -address of the remote node): +address of the remote node and the the `X` in the interface address must be +unique among all nodes, e.g. 0, 1, 2, ...): ``` -vpncloud -c remote_node:3210 -``` - -Then, the interfaces have to configured and activated (the `X` in the address -must be unique among all nodes, e.g. 0, 1, 2, ...): -``` -ifconfig vpncloud0 10.0.0.X/24 mtu 1400 up +vpncloud -c remote_node:3210 --ifup 'ifconfig $IFNAME 10.0.0.X/24 mtu 1400 up' ``` Afterwards, the interface can be used to communicate. @@ -157,12 +166,9 @@ Afterwards, the interface can be used to communicate. In this example, 4 nodes should communicate using IP. First, VpnCloud need to be started on both nodes: ``` -vpncloud -t tun -c remote_node:3210 --subnet 10.0.0.1/32 +vpncloud -t tun -c remote_node:3210 --subnet 10.0.0.X/32 --ifup 'ifconfig $IFNAME 10.0.0.0/24 mtu 1400 up' ``` -Then, the interfaces can be configured and activated like in the previous -example. - ### Important notes