diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-03-06 16:37:23 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-03-07 07:20:24 +0100 |
| commit | 4917a64ac305bc157e3f78345c51b40d5ceea822 (patch) | |
| tree | f1eaa60ac25d55a64a998b4f316ffd343d4a542a | |
| parent | 526c2e19e0e2acfd8a1945a916ab84dd652453de (diff) | |
| download | mullvadvpn-4917a64ac305bc157e3f78345c51b40d5ceea822.tar.xz mullvadvpn-4917a64ac305bc157e3f78345c51b40d5ceea822.zip | |
Add IPC capabilities to OpenVPN plugin
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/Cargo.toml | 3 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/structs.rs | 2 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/lib.rs | 32 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/processing.rs | 30 |
5 files changed, 52 insertions, 16 deletions
diff --git a/Cargo.lock b/Cargo.lock index 63d6b95fa8..ab64cc5d51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ dependencies = [ "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "talpid_ipc 0.1.0", ] [[package]] diff --git a/talpid_openvpn_plugin/Cargo.toml b/talpid_openvpn_plugin/Cargo.toml index 79c0f387cb..ca870cb1cb 100644 --- a/talpid_openvpn_plugin/Cargo.toml +++ b/talpid_openvpn_plugin/Cargo.toml @@ -12,5 +12,8 @@ error-chain = "0.8" log = "0.3" env_logger = "0.4" +[dependencies.talpid_ipc] +path = "../talpid_ipc" + [dev-dependencies] assert_matches = "1.0" diff --git a/talpid_openvpn_plugin/src/ffi/structs.rs b/talpid_openvpn_plugin/src/ffi/structs.rs index ba5bc2b343..b80f7ae2a2 100644 --- a/talpid_openvpn_plugin/src/ffi/structs.rs +++ b/talpid_openvpn_plugin/src/ffi/structs.rs @@ -4,7 +4,7 @@ use std::os::raw::{c_char, c_int, c_uint, c_void}; #[repr(C)] pub struct openvpn_plugin_args_open_in { type_mask: c_int, - argv: *const *const c_char, + pub argv: *const *const c_char, envp: *const *const c_char, callbacks: *const c_void, ssl_api: ovpnSSLAPI, diff --git a/talpid_openvpn_plugin/src/lib.rs b/talpid_openvpn_plugin/src/lib.rs index 4eb2a0f336..9a9aea8c6c 100644 --- a/talpid_openvpn_plugin/src/lib.rs +++ b/talpid_openvpn_plugin/src/lib.rs @@ -9,6 +9,8 @@ extern crate env_logger; #[macro_use] extern crate assert_matches; +extern crate talpid_ipc; + use std::os::raw::{c_int, c_void}; mod ffi; @@ -29,6 +31,12 @@ error_chain!{ ParseEnvFailed { description("Unable to parse environment variables from OpenVPN") } + ParseArgsFailed { + description("Unable to parse arguments from OpenVPN") + } + EventProcessingFailed { + description("Failed to process the event") + } } } @@ -45,13 +53,13 @@ pub static INTERESTING_EVENTS: &'static [OpenVpnPluginEvent] = &[OpenVpnPluginEv /// plugin. #[no_mangle] pub extern "C" fn openvpn_plugin_open_v3(_version: c_int, - _args: *const ffi::openvpn_plugin_args_open_in, + args: *const ffi::openvpn_plugin_args_open_in, retptr: *mut ffi::openvpn_plugin_args_open_return) -> c_int { if init_logger().is_err() { return ffi::OPENVPN_PLUGIN_FUNC_ERROR; } - match openvpn_plugin_open_v3_internal(retptr) { + match openvpn_plugin_open_v3_internal(args, retptr) { Ok(_) => ffi::OPENVPN_PLUGIN_FUNC_SUCCESS, Err(e) => { log_error("Unable to initialize plugin", &e); @@ -60,19 +68,31 @@ pub extern "C" fn openvpn_plugin_open_v3(_version: c_int, } } -fn openvpn_plugin_open_v3_internal(retptr: *mut ffi::openvpn_plugin_args_open_return) +fn openvpn_plugin_open_v3_internal(args: *const ffi::openvpn_plugin_args_open_in, + retptr: *mut ffi::openvpn_plugin_args_open_return) -> Result<()> { debug!("Initializing plugin"); - let handle = Box::new(EventProcessor::new().chain_err(|| ErrorKind::InitHandleFailed)?); + let core_server_id = parse_args(args)?; + let processor = EventProcessor::new(core_server_id).chain_err(|| ErrorKind::InitHandleFailed)?; unsafe { (*retptr).type_mask = ffi::events_to_bitmask(INTERESTING_EVENTS); // Converting the handle into a raw pointer will make it escape Rust deallocation. See // `openvpn_plugin_close_v1` for deallocation. - (*retptr).handle = Box::into_raw(handle) as *const c_void; + (*retptr).handle = Box::into_raw(Box::new(processor)) as *const c_void; } Ok(()) } +fn parse_args(args: *const ffi::openvpn_plugin_args_open_in) -> Result<talpid_ipc::IpcServerId> { + let mut args_iter = unsafe { ffi::parse::string_array((*args).argv) } + .chain_err(|| ErrorKind::ParseArgsFailed)? + .into_iter(); + let _plugin_path = args_iter.next(); + let core_server_id = args_iter.next() + .ok_or(ErrorKind::Msg("No core server id given as first argument".to_owned()))?; + Ok(core_server_id) +} + /// Called by OpenVPN just before the plugin is unloaded. Should correctly close the plugin and /// deallocate any `handle` initialized by the plugin in `openvpn_plugin_open_v3` @@ -108,7 +128,7 @@ fn openvpn_plugin_func_v3_internal(args: *const ffi::openvpn_plugin_args_func_in let env = unsafe { ffi::parse::env((*args).envp) }.chain_err(|| ErrorKind::ParseEnvFailed)?; let mut handle = unsafe { Box::from_raw((*args).handle as *mut EventProcessor) }; - handle.process_event(event, env); + handle.process_event(event, env).chain_err(|| ErrorKind::EventProcessingFailed)?; // Convert the handle back to a raw pointer to not deallocate it when we return. Box::into_raw(handle); diff --git a/talpid_openvpn_plugin/src/processing.rs b/talpid_openvpn_plugin/src/processing.rs index 337030744e..586d0574ec 100644 --- a/talpid_openvpn_plugin/src/processing.rs +++ b/talpid_openvpn_plugin/src/processing.rs @@ -1,24 +1,36 @@ - - use ffi::OpenVpnPluginEvent; + use std::collections::HashMap; +use talpid_ipc::{IpcClient, IpcServerId}; -error_chain!{} +error_chain! { + errors { + IpcSendingError { + description("Failed while sending an event over the IPC channel") + } + } +} /// Struct processing OpenVPN events and notifies listeners over IPC -pub struct EventProcessor; +pub struct EventProcessor { + ipc_client: IpcClient<HashMap<String, String>>, +} impl EventProcessor { - pub fn new() -> Result<EventProcessor> { + pub fn new(server_id: IpcServerId) -> Result<EventProcessor> { debug!("Creating EventProcessor"); - Ok(EventProcessor) + let ipc_client = IpcClient::new(server_id); + Ok(EventProcessor { ipc_client: ipc_client }) } - pub fn process_event(&mut self, event: OpenVpnPluginEvent, _env: HashMap<String, String>) { - // TODO(linus): This is where we should send events to core. - trace!("Hello from EventProcessor: {:?}", event); + pub fn process_event(&mut self, + event: OpenVpnPluginEvent, + env: HashMap<String, String>) + -> Result<()> { + trace!("Processing \"{:?}\" event", event); + self.ipc_client.send(&env).chain_err(|| ErrorKind::IpcSendingError) } } |
