diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-02-28 18:30:10 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-03-02 14:41:18 +0100 |
| commit | 1e546d46fba261a3e3b6c4ea43f4a7e16aa64c5b (patch) | |
| tree | 566838781d0413a56a4331876692dcc2b7594ce1 | |
| parent | f3226b945964b18e5cba9df7f7cc1347229ed9a8 (diff) | |
| download | mullvadvpn-1e546d46fba261a3e3b6c4ea43f4a7e16aa64c5b.tar.xz mullvadvpn-1e546d46fba261a3e3b6c4ea43f4a7e16aa64c5b.zip | |
Move the openvpn functions to the top
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/consts.rs | 1 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/mod.rs | 148 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/structs.rs | 49 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/lib.rs | 101 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/processing.rs | 29 |
5 files changed, 168 insertions, 160 deletions
diff --git a/talpid_openvpn_plugin/src/ffi/consts.rs b/talpid_openvpn_plugin/src/ffi/consts.rs index 81fe134b9e..34f6f6c44b 100644 --- a/talpid_openvpn_plugin/src/ffi/consts.rs +++ b/talpid_openvpn_plugin/src/ffi/consts.rs @@ -44,6 +44,7 @@ impl OpenVpnPluginEvent { // Accept (success) or decline (error) an operation, such as incoming client connection attempt. pub const OPENVPN_PLUGIN_FUNC_SUCCESS: c_int = 0; pub const OPENVPN_PLUGIN_FUNC_ERROR: c_int = 1; +#[allow(dead_code)] pub const OPENVPN_PLUGIN_FUNC_DEFERRED: c_int = 2; diff --git a/talpid_openvpn_plugin/src/ffi/mod.rs b/talpid_openvpn_plugin/src/ffi/mod.rs index 17d904c38b..fe046cde67 100644 --- a/talpid_openvpn_plugin/src/ffi/mod.rs +++ b/talpid_openvpn_plugin/src/ffi/mod.rs @@ -2,155 +2,21 @@ // the original declarations of these structs and functions along with documentation for them: // https://github.com/OpenVPN/openvpn/blob/master/include/openvpn-plugin.h.in -use std::os::raw::{c_char, c_int, c_uint, c_void}; +use std::os::raw::c_int; +mod consts; +pub use self::consts::*; -#[allow(dead_code)] -pub mod consts; -use self::consts::*; +mod structs; +pub use self::structs::*; -mod parse; +pub mod parse; -error_chain!{ - errors { - HandlerInitFailed { - description("Unable to initialize EventProcessor") - } - InvalidEventType { - description("Invalid event type constant") - } - ParseEnvFailed { - description("Unable to parse environment variables from OpenVPN") - } - } -} - -/// All the OpenVPN events this plugin will register for listening to. Edit this variable to change -/// events. -pub static INTERESTING_EVENTS: &'static [OpenVpnPluginEvent] = &[OpenVpnPluginEvent::Up, - OpenVpnPluginEvent::RoutePredown]; - - -/// Struct sent to `openvpn_plugin_open_v3` containing input values. -#[repr(C)] -pub struct openvpn_plugin_args_open_in { - type_mask: c_int, - argv: *const *const c_char, - envp: *const *const c_char, - callbacks: *const c_void, - ssl_api: ovpnSSLAPI, - ovpn_version: *const c_char, - ovpn_version_major: c_uint, - ovpn_version_minor: c_uint, - ovpn_version_patch: *const c_char, -} - -#[allow(dead_code)] -#[repr(C)] -enum ovpnSSLAPI { - SSLAPI_NONE, - SSLAPI_OPENSSL, - SSLAPI_MBEDTLS, -} - -/// Struct used for returning values from `openvpn_plugin_open_v3` to OpenVPN. -#[repr(C)] -pub struct openvpn_plugin_args_open_return { - type_mask: c_int, - handle: *const c_void, - return_list: *const c_void, -} - -/// Struct sent to `openvpn_plugin_func_v3` containing input values. -#[repr(C)] -pub struct openvpn_plugin_args_func_in { - event_type: c_int, - argv: *const *const c_char, - envp: *const *const c_char, - handle: *const c_void, - per_client_context: *const c_void, - current_cert_depth: c_int, - current_cert: *const c_void, -} - -/// Struct used for returning values from `openvpn_plugin_func_v3` to OpenVPN. -#[repr(C)] -pub struct openvpn_plugin_args_func_return { - return_list: *const c_void, -} - - -/// Called by OpenVPN when the plugin is first loaded. -/// Used to register which events the plugin wants to listen to (`args.type_mask`). Can also set an -/// arbitrary object inside `args.handle` that will then be passed to all subsequent calls to the -/// plugin. -#[no_mangle] -pub extern "C" fn openvpn_plugin_open_v3(_version: c_int, - _args: *const openvpn_plugin_args_open_in, - retptr: *mut openvpn_plugin_args_open_return) - -> c_int { - println!("openvpn_plugin_open_v3()"); - // TODO(linus): Add logging of errors - match openvpn_plugin_open_v3_internal(retptr) { - Ok(_) => OPENVPN_PLUGIN_FUNC_SUCCESS, - Err(_) => OPENVPN_PLUGIN_FUNC_ERROR, - } -} - -fn openvpn_plugin_open_v3_internal(retptr: *mut openvpn_plugin_args_open_return) -> Result<()> { - let handle = Box::new(::EventProcessor::new().chain_err(|| ErrorKind::HandlerInitFailed)?); - unsafe { - (*retptr).type_mask = 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; - } - Ok(()) -} - - -/// 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` -#[no_mangle] -pub extern "C" fn openvpn_plugin_close_v1(handle: *const c_void) { - println!("openvpn_plugin_close_v1()"); - // IMPORTANT: Bring the handle object back from a raw pointer. This will cause the handle - // object to be properly deallocated right here. - let _ = unsafe { Box::from_raw(handle as *mut ::EventProcessor) }; -} - -/// Called by OpenVPN for each OPENVPN_PLUGIN_* event that it registered for in -/// `openvpn_plugin_open_v3` -#[no_mangle] -pub extern "C" fn openvpn_plugin_func_v3(_version: c_int, - args: *const openvpn_plugin_args_func_in, - _retptr: *const openvpn_plugin_args_func_return) - -> c_int { - // TODO(linus): Add logging of errors - match openvpn_plugin_func_v3_internal(args) { - Ok(_) => OPENVPN_PLUGIN_FUNC_SUCCESS, - Err(_) => OPENVPN_PLUGIN_FUNC_ERROR, - } -} - -fn openvpn_plugin_func_v3_internal(args: *const openvpn_plugin_args_func_in) -> Result<()> { - let event_type = unsafe { (*args).event_type }; - let event = OpenVpnPluginEvent::from_int(event_type).chain_err(|| ErrorKind::InvalidEventType)?; - println!("openvpn_plugin_func_v3({:?})", event); - let env = unsafe { 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); - // Convert the handle back to a raw pointer to not deallocate it when we return. - Box::into_raw(handle); - - Ok(()) -} /// Translates a collection of `OpenVpnPluginEvent` instances into a bitmask in the format OpenVPN /// expects it. -fn events_to_bitmask(events: &[OpenVpnPluginEvent]) -> c_int { +pub fn events_to_bitmask(events: &[OpenVpnPluginEvent]) -> c_int { let mut bitmask: c_int = 0; for event in events { bitmask |= 1 << (*event as i32); diff --git a/talpid_openvpn_plugin/src/ffi/structs.rs b/talpid_openvpn_plugin/src/ffi/structs.rs new file mode 100644 index 0000000000..325f312974 --- /dev/null +++ b/talpid_openvpn_plugin/src/ffi/structs.rs @@ -0,0 +1,49 @@ +use std::os::raw::{c_char, c_int, c_uint, c_void}; + +/// Struct sent to `openvpn_plugin_open_v3` containing input values. +#[repr(C)] +pub struct openvpn_plugin_args_open_in { + type_mask: c_int, + argv: *const *const c_char, + envp: *const *const c_char, + callbacks: *const c_void, + ssl_api: ovpnSSLAPI, + ovpn_version: *const c_char, + ovpn_version_major: c_uint, + ovpn_version_minor: c_uint, + ovpn_version_patch: *const c_char, +} + +#[allow(dead_code)] +#[repr(C)] +enum ovpnSSLAPI { + SSLAPI_NONE, + SSLAPI_OPENSSL, + SSLAPI_MBEDTLS, +} + +/// Struct used for returning values from `openvpn_plugin_open_v3` to OpenVPN. +#[repr(C)] +pub struct openvpn_plugin_args_open_return { + pub type_mask: c_int, + pub handle: *const c_void, + return_list: *const c_void, +} + +/// Struct sent to `openvpn_plugin_func_v3` containing input values. +#[repr(C)] +pub struct openvpn_plugin_args_func_in { + pub event_type: c_int, + argv: *const *const c_char, + pub envp: *const *const c_char, + pub handle: *const c_void, + per_client_context: *const c_void, + current_cert_depth: c_int, + current_cert: *const c_void, +} + +/// Struct used for returning values from `openvpn_plugin_func_v3` to OpenVPN. +#[repr(C)] +pub struct openvpn_plugin_args_func_return { + return_list: *const c_void, +} diff --git a/talpid_openvpn_plugin/src/lib.rs b/talpid_openvpn_plugin/src/lib.rs index 49e4ce031c..cff9430d61 100644 --- a/talpid_openvpn_plugin/src/lib.rs +++ b/talpid_openvpn_plugin/src/lib.rs @@ -8,38 +8,101 @@ extern crate error_chain; #[macro_use] extern crate assert_matches; -use std::collections::HashMap; - +use std::os::raw::{c_int, c_void}; mod ffi; +mod processing; -/// Publicly export the functions making up the public interface of the plugin. These are the C FFI -/// functions called by OpenVPN. -pub use ffi::{openvpn_plugin_open_v3, openvpn_plugin_close_v1, openvpn_plugin_func_v3}; +use ffi::OpenVpnPluginEvent; +use processing::EventProcessor; -use ffi::consts::OpenVpnPluginEvent; +error_chain!{ + errors { + InitHandleFailed { + description("Unable to initialize event processor") + } + InvalidEventType { + description("Invalid event type constant") + } + ParseEnvFailed { + description("Unable to parse environment variables from OpenVPN") + } + } +} -error_chain!{} +/// All the OpenVPN events this plugin will register for listening to. Edit this variable to change +/// events. +pub static INTERESTING_EVENTS: &'static [OpenVpnPluginEvent] = &[OpenVpnPluginEvent::Up, + OpenVpnPluginEvent::RoutePredown]; -/// Struct processing OpenVPN events and notifies listeners over IPC -struct EventProcessor; -impl EventProcessor { - pub fn new() -> Result<EventProcessor> { - Ok(EventProcessor) +/// Called by OpenVPN when the plugin is first loaded. +/// Used to register which events the plugin wants to listen to (`args.type_mask`). Can also set an +/// arbitrary pointer inside `args.handle` that will then be passed to all subsequent calls to the +/// plugin. +#[no_mangle] +pub extern "C" fn openvpn_plugin_open_v3(_version: c_int, + _args: *const ffi::openvpn_plugin_args_open_in, + retptr: *mut ffi::openvpn_plugin_args_open_return) + -> c_int { + println!("openvpn_plugin_open_v3()"); + // TODO(linus): Add logging of errors + match openvpn_plugin_open_v3_internal(retptr) { + Ok(_) => ffi::OPENVPN_PLUGIN_FUNC_SUCCESS, + Err(_) => ffi::OPENVPN_PLUGIN_FUNC_ERROR, } +} - pub fn process_event(&mut self, event: OpenVpnPluginEvent, env: HashMap<String, String>) { - // TODO(linus): This is where we should send events to core. - println!("Hello from EventProcessor: {:?}", event); +fn openvpn_plugin_open_v3_internal(retptr: *mut ffi::openvpn_plugin_args_open_return) + -> Result<()> { + let handle = Box::new(EventProcessor::new().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; } + Ok(()) +} + + +/// 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` +#[no_mangle] +pub extern "C" fn openvpn_plugin_close_v1(handle: *const c_void) { + println!("openvpn_plugin_close_v1()"); + // IMPORTANT: Bring the handle object back from a raw pointer. This will cause the handle + // object to be properly deallocated right here. + let _ = unsafe { Box::from_raw(handle as *mut EventProcessor) }; } -impl Drop for EventProcessor { - fn drop(&mut self) { - // TODO(linus): If we need, this is where we send some shutdown event or similar to core. - println!("Dropping EventProcessor!"); + +/// Called by OpenVPN for each OPENVPN_PLUGIN_* event that it registered for in +/// `openvpn_plugin_open_v3` +#[no_mangle] +pub extern "C" fn openvpn_plugin_func_v3(_version: c_int, + args: *const ffi::openvpn_plugin_args_func_in, + _retptr: *const ffi::openvpn_plugin_args_func_return) + -> c_int { + // TODO(linus): Add logging of errors + match openvpn_plugin_func_v3_internal(args) { + Ok(_) => ffi::OPENVPN_PLUGIN_FUNC_SUCCESS, + Err(_) => ffi::OPENVPN_PLUGIN_FUNC_ERROR, } } + +fn openvpn_plugin_func_v3_internal(args: *const ffi::openvpn_plugin_args_func_in) -> Result<()> { + let event_type = unsafe { (*args).event_type }; + let event = OpenVpnPluginEvent::from_int(event_type).chain_err(|| ErrorKind::InvalidEventType)?; + let env = unsafe { ffi::parse::env((*args).envp) }.chain_err(|| ErrorKind::ParseEnvFailed)?; + println!("openvpn_plugin_func_v3({:?})", event); + + let mut handle = unsafe { Box::from_raw((*args).handle as *mut EventProcessor) }; + handle.process_event(event, env); + // Convert the handle back to a raw pointer to not deallocate it when we return. + Box::into_raw(handle); + + Ok(()) +} diff --git a/talpid_openvpn_plugin/src/processing.rs b/talpid_openvpn_plugin/src/processing.rs new file mode 100644 index 0000000000..405e279896 --- /dev/null +++ b/talpid_openvpn_plugin/src/processing.rs @@ -0,0 +1,29 @@ + + +use ffi::OpenVpnPluginEvent; +use std::collections::HashMap; + + +error_chain!{} + + +/// Struct processing OpenVPN events and notifies listeners over IPC +pub struct EventProcessor; + +impl EventProcessor { + pub fn new() -> Result<EventProcessor> { + Ok(EventProcessor) + } + + pub fn process_event(&mut self, event: OpenVpnPluginEvent, _env: HashMap<String, String>) { + // TODO(linus): This is where we should send events to core. + println!("Hello from EventProcessor: {:?}", event); + } +} + +impl Drop for EventProcessor { + fn drop(&mut self) { + // TODO(linus): If we need, this is where we send some shutdown event or similar to core. + println!("Dropping EventProcessor!"); + } +} |
