summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-07-20 08:26:19 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-07-20 08:26:19 +0200
commite0b25ea79254932aa1bdfb58544ec3ecf5eaa083 (patch)
treeedc583f2c5ec3b85982e49ca6ff249af563a2faa
parent3ed79a04900596968495303e068b9e80ef73bbbe (diff)
parentfe0646dc2670bf8e9afa5dfcd408b37cc44843f4 (diff)
downloadmullvadvpn-e0b25ea79254932aa1bdfb58544ec3ecf5eaa083.tar.xz
mullvadvpn-e0b25ea79254932aa1bdfb58544ec3ecf5eaa083.zip
Merge branch 'new-openvpn-plugin-crate'
-rw-r--r--Cargo.lock13
-rw-r--r--Cargo.toml1
-rw-r--r--openvpn-ffi/Cargo.toml13
-rw-r--r--openvpn-ffi/src/lib.rs151
-rw-r--r--openvpn-ffi/src/parse.rs146
-rw-r--r--openvpn-ffi/src/structs.rs49
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/lib.rs2
-rw-r--r--talpid-core/src/process/openvpn.rs2
-rw-r--r--talpid-core/src/tunnel/mod.rs2
-rw-r--r--talpid-core/src/tunnel/openvpn.rs18
-rw-r--r--talpid-openvpn-plugin/Cargo.toml2
-rw-r--r--talpid-openvpn-plugin/src/lib.rs131
-rw-r--r--talpid-openvpn-plugin/src/processing.rs17
14 files changed, 59 insertions, 490 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3903f4a902..b4c1afb5e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5,7 +5,7 @@ dependencies = [
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "openvpn-ffi 0.1.0",
+ "openvpn-plugin 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"talpid-ipc 0.1.0",
]
@@ -500,11 +500,11 @@ dependencies = [
]
[[package]]
-name = "openvpn-ffi"
-version = "0.1.0"
+name = "openvpn-plugin"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -723,7 +723,7 @@ dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mktemp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openvpn-ffi 0.1.0",
+ "openvpn-plugin 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"talpid-ipc 0.1.0",
]
@@ -998,6 +998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c"
+"checksum openvpn-plugin 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99c05a2229a24799412627dd22730729796aca97405dedc297a622536f37fb3b"
"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "37f364e2ce5efa24c7d0b6646d5bb61145551a0112f107ffd7499f1a3e322fbd"
diff --git a/Cargo.toml b/Cargo.toml
index 7c598c504c..a1d53676c5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,5 +6,4 @@ members = [
"talpid-openvpn-plugin",
"talpid-core",
"talpid-ipc",
- "openvpn-ffi",
]
diff --git a/openvpn-ffi/Cargo.toml b/openvpn-ffi/Cargo.toml
deleted file mode 100644
index fd739707f0..0000000000
--- a/openvpn-ffi/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "openvpn-ffi"
-version = "0.1.0"
-authors = ["Linus Färnstrand <linus@mullvad.net>", "Erik Larkö <erik@mullvad.net>"]
-description = "Constants, enums and structs for interfacing with OpenVPN"
-
-[dependencies]
-error-chain = "0.10"
-serde = "1.0"
-serde_derive = "1.0"
-
-[dev-dependencies]
-assert_matches = "1.0"
diff --git a/openvpn-ffi/src/lib.rs b/openvpn-ffi/src/lib.rs
deleted file mode 100644
index 934eb091df..0000000000
--- a/openvpn-ffi/src/lib.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-//! Constants for OpenVPN. Taken from include/openvpn-plugin.h in the OpenVPN repository:
-//! https://github.com/OpenVPN/openvpn/blob/master/include/openvpn-plugin.h.in
-
-#[macro_use]
-extern crate error_chain;
-
-#[macro_use]
-extern crate serde_derive;
-
-#[cfg(test)]
-#[macro_use]
-extern crate assert_matches;
-
-
-use std::collections::HashMap;
-use std::os::raw::c_int;
-
-mod structs;
-pub use structs::*;
-
-pub mod parse;
-
-error_chain!{
- errors {
- InvalidEnumVariant(i: c_int) {
- description("Integer does not match any enum variant")
- display("{} is not a valid OPENVPN_PLUGIN_* constant", i)
- }
- }
-}
-
-
-/// Type definition for environment variables from OpenVPN
-pub type OpenVpnEnv = HashMap<String, String>;
-
-
-// Return values. Returned from the plugin to OpenVPN to indicate success or failure. Can also
-// 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;
-pub const OPENVPN_PLUGIN_FUNC_DEFERRED: c_int = 2;
-
-
-/// Enum whose variants correspond to the `OPENVPN_PLUGIN_*` event constants.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
-pub enum OpenVpnPluginEvent {
- Up = 0,
- Down = 1,
- RouteUp = 2,
- IpChange = 3,
- TlsVerify = 4,
- AuthUserPassVerify = 5,
- ClientConnect = 6,
- ClientDisconnect = 7,
- LearnAddress = 8,
- ClientConnectV2 = 9,
- TlsFinal = 10,
- EnablePf = 11,
- RoutePredown = 12,
- N = 13,
-}
-
-impl OpenVpnPluginEvent {
- /// Tries to parse an integer from C into a variant of `OpenVpnPluginEvent`.
- pub fn from_int(i: c_int) -> Result<OpenVpnPluginEvent> {
- if i >= OpenVpnPluginEvent::Up as c_int && i <= OpenVpnPluginEvent::N as c_int {
- Ok(unsafe { ::std::mem::transmute_copy::<c_int, OpenVpnPluginEvent>(&i) },)
- } else {
- bail!(ErrorKind::InvalidEnumVariant(i));
- }
- }
-}
-
-/// Translates a collection of `OpenVpnPluginEvent` instances into a bitmask in the format OpenVPN
-/// expects it.
-pub fn events_to_bitmask(events: &[OpenVpnPluginEvent]) -> c_int {
- let mut bitmask: c_int = 0;
- for event in events {
- bitmask |= 1 << (*event as i32);
- }
- bitmask
-}
-
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn from_int_first() {
- let result = OpenVpnPluginEvent::from_int(0);
- assert_matches!(result, Ok(OpenVpnPluginEvent::Up));
- }
-
- #[test]
- fn from_int_last() {
- let result = OpenVpnPluginEvent::from_int(13);
- assert_matches!(result, Ok(OpenVpnPluginEvent::N));
- }
-
- #[test]
- fn from_int_all_valid() {
- for i in 0..13 {
- if OpenVpnPluginEvent::from_int(i).is_err() {
- panic!("{} not covered", i);
- }
- }
- }
-
- #[test]
- fn from_int_negative() {
- let result = OpenVpnPluginEvent::from_int(-5);
- assert_matches!(result, Err(Error(ErrorKind::InvalidEnumVariant(-5), _)));
- }
-
- #[test]
- fn from_int_invalid() {
- let result = OpenVpnPluginEvent::from_int(14);
- assert_matches!(result, Err(Error(ErrorKind::InvalidEnumVariant(14), _)));
- }
-
- #[test]
- fn event_enum_to_str() {
- let result = format!("{:?}", OpenVpnPluginEvent::Up);
- assert_eq!("Up", result);
- }
-
- #[test]
- fn events_to_bitmask_no_events() {
- let result = events_to_bitmask(&[]);
- assert_eq!(0, result);
- }
-
- #[test]
- fn events_to_bitmask_one_event() {
- let result = events_to_bitmask(&[OpenVpnPluginEvent::Up]);
- assert_eq!(0b1, result);
- }
-
- #[test]
- fn events_to_bitmask_another_event() {
- let result = events_to_bitmask(&[OpenVpnPluginEvent::RouteUp]);
- assert_eq!(0b100, result);
- }
-
- #[test]
- fn events_to_bitmask_many_events() {
- let result = events_to_bitmask(&[OpenVpnPluginEvent::RouteUp, OpenVpnPluginEvent::N]);
- assert_eq!((1 << 13) + (1 << 2), result);
- }
-}
diff --git a/openvpn-ffi/src/parse.rs b/openvpn-ffi/src/parse.rs
deleted file mode 100644
index 6d0c42c06f..0000000000
--- a/openvpn-ffi/src/parse.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-use std::collections::HashMap;
-use std::ffi::CStr;
-use std::os::raw::c_char;
-
-error_chain!{
- errors {
- Null {
- description("Input is null pointer")
- }
- NoEqual(s: String) {
- description("No equal sign in string")
- display("No equal sign in \"{}\"", s)
- }
- }
- foreign_links {
- InvalidContent(::std::str::Utf8Error);
- }
-}
-
-
-/// Parses a null-terminated C string array into a Vec<String> for safe usage.
-///
-/// Returns an Err if given a null pointer or if a string is not valid utf-8.
-///
-/// # Segfaults
-///
-/// Can cause the program to crash if the pointer array starting at `ptr` is not correctly null
-/// terminated. Likewise, if any string pointed to is not properly null-terminated it may crash.
-pub unsafe fn string_array(mut ptr: *const *const c_char) -> Result<Vec<String>> {
- if ptr.is_null() {
- bail!(ErrorKind::Null);
- } else {
- let mut strings = Vec::new();
- while !(*ptr).is_null() {
- let cstr = CStr::from_ptr(*ptr);
- strings.push(cstr.to_str()?.to_owned());
- ptr = ptr.offset(1);
- }
- Ok(strings)
- }
-}
-
-
-/// Parses a null-terminated array of C strings with "=" delimiters into a key-value map.
-///
-/// The input environment has to contain null-terminated strings containing at least
-/// one equal sign ("="). Every string is split at the first equal sign and added to the map with
-/// the first part being the key and the second the value.
-///
-/// If multiple entries have the same key, the last one will be in the result map.
-///
-/// # Segfaults
-///
-/// Uses `string_array` internally and will segfault for the same reasons as that function.
-pub unsafe fn env(envptr: *const *const c_char) -> Result<::OpenVpnEnv> {
- let mut map = HashMap::new();
- for string in string_array(envptr)? {
- let mut iter = string.splitn(2, '=');
- let key = iter.next().unwrap();
- let value = iter.next().ok_or_else(|| Error::from(ErrorKind::NoEqual(string.clone())))?;
- map.insert(key.to_owned(), value.to_owned());
- }
- Ok(map)
-}
-
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::os::raw::c_char;
- use std::ptr;
-
- #[test]
- fn string_array_null() {
- let result = unsafe { string_array(ptr::null()) };
- assert_matches!(result, Err(Error(ErrorKind::Null, _)));
- }
-
- #[test]
- fn string_array_empty() {
- let ptr_arr = [ptr::null()];
- let result = unsafe { string_array(&ptr_arr as *const *const c_char).unwrap() };
- assert!(result.is_empty());
- }
-
- #[test]
- fn string_array_no_space_trim() {
- let test_str = " foobar \0";
- let ptr_arr = [test_str as *const _ as *const c_char, ptr::null()];
- let result = unsafe { string_array(&ptr_arr as *const *const c_char).unwrap() };
- assert_eq!([" foobar "], &result[..]);
- }
-
- #[test]
- fn string_array_two_strings() {
- let test_str1 = "foobar\0";
- let test_str2 = "barbaz\0";
- let ptr_arr = [
- test_str1 as *const _ as *const c_char,
- test_str2 as *const _ as *const c_char,
- ptr::null(),
- ];
- let result = unsafe { string_array(&ptr_arr as *const *const c_char).unwrap() };
- assert_eq!(["foobar", "barbaz"], &result[..]);
- }
-
- #[test]
- fn env_one_value() {
- let test_str = "var_a=value_b\0";
- let ptr_arr = [test_str as *const _ as *const c_char, ptr::null()];
- let result = unsafe { env(&ptr_arr as *const *const c_char).unwrap() };
- assert_eq!(1, result.len());
- assert_eq!(Some("value_b"), result.get("var_a").map(|s| &s[..]));
- }
-
- #[test]
- fn env_no_equal() {
- let test_str = "foobar\0";
- let ptr_arr = [test_str as *const _ as *const c_char, ptr::null()];
- let result = unsafe { env(&ptr_arr as *const *const c_char) };
- assert_matches!(result, Err(Error(ErrorKind::NoEqual(_), _)));
- }
-
- #[test]
- fn env_double_equal() {
- let test_str = "foo=bar=baz\0";
- let ptr_arr = [test_str as *const _ as *const c_char, ptr::null()];
- let env = unsafe { env(&ptr_arr as *const *const c_char).unwrap() };
- assert_eq!(1, env.len());
- assert_eq!(Some("bar=baz"), env.get("foo").map(|s| &s[..]));
- }
-
- #[test]
- fn env_two_same_key() {
- let test_str1 = "foo=123\0";
- let test_str2 = "foo=abc\0";
- let ptr_arr = [
- test_str1 as *const _ as *const c_char,
- test_str2 as *const _ as *const c_char,
- ptr::null(),
- ];
- let env = unsafe { env(&ptr_arr as *const *const c_char).unwrap() };
- assert_eq!(1, env.len());
- assert_eq!(Some("abc"), env.get("foo").map(|s| &s[..]));
- }
-}
diff --git a/openvpn-ffi/src/structs.rs b/openvpn-ffi/src/structs.rs
deleted file mode 100644
index b80f7ae2a2..0000000000
--- a/openvpn-ffi/src/structs.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-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,
- pub 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 {
- None,
- OpenSsl,
- 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-core/Cargo.toml b/talpid-core/Cargo.toml
index 2be5457e26..96c30924e2 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -13,7 +13,7 @@ lazy_static = "0.2"
log = "0.3"
mktemp = "0.3"
-openvpn-ffi = { path = "../openvpn-ffi" }
+openvpn-plugin = { version = "0.2", features = ["serialize"] }
talpid-ipc = { path = "../talpid-ipc" }
[target.'cfg(unix)'.dependencies]
diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs
index 1fc92f8fe4..29ab0377e5 100644
--- a/talpid-core/src/lib.rs
+++ b/talpid-core/src/lib.rs
@@ -21,7 +21,7 @@ extern crate jsonrpc_core;
extern crate jsonrpc_macros;
extern crate talpid_ipc;
-extern crate openvpn_ffi;
+extern crate openvpn_plugin;
/// Working with processes.
pub mod process;
diff --git a/talpid-core/src/process/openvpn.rs b/talpid-core/src/process/openvpn.rs
index ea66ef894c..6b671b767c 100644
--- a/talpid-core/src/process/openvpn.rs
+++ b/talpid-core/src/process/openvpn.rs
@@ -1,5 +1,3 @@
-extern crate openvpn_ffi;
-
use duct;
use net;
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index b05f1283f3..3835e26632 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -1,6 +1,6 @@
use mktemp;
use net;
-use openvpn_ffi::OpenVpnPluginEvent;
+use openvpn_plugin::types::OpenVpnPluginEvent;
use process::openvpn::OpenVpnCommand;
use std::fs;
use std::io::{self, Write};
diff --git a/talpid-core/src/tunnel/openvpn.rs b/talpid-core/src/tunnel/openvpn.rs
index 08c2c14a32..f545a1d4d1 100644
--- a/talpid-core/src/tunnel/openvpn.rs
+++ b/talpid-core/src/tunnel/openvpn.rs
@@ -1,8 +1,9 @@
use duct;
use jsonrpc_core::{Error, IoHandler};
-use openvpn_ffi::{OpenVpnEnv, OpenVpnPluginEvent};
+use openvpn_plugin::types::OpenVpnPluginEvent;
use process::openvpn::OpenVpnCommand;
+use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::result::Result as StdResult;
@@ -47,7 +48,7 @@ impl OpenVpnMonitor {
/// Creates a new `OpenVpnMonitor` with the given listener and using the plugin at the given
/// path.
pub fn new<L, P>(mut cmd: OpenVpnCommand, on_event: L, plugin_path: P) -> Result<Self>
- where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static,
+ where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static,
P: AsRef<Path>
{
let event_dispatcher = OpenVpnEventDispatcher::start(on_event)
@@ -180,7 +181,7 @@ pub struct OpenVpnEventDispatcher {
impl OpenVpnEventDispatcher {
/// Construct and start the IPC server with the given event listener callback.
pub fn start<L>(on_event: L) -> talpid_ipc::Result<Self>
- where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static
+ where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static
{
let rpc = OpenVpnEventApiImpl { on_event };
let mut io = IoHandler::new();
@@ -215,7 +216,7 @@ mod api {
#[rpc(name = "openvpn_event")]
fn openvpn_event(&self,
OpenVpnPluginEvent,
- OpenVpnEnv)
+ HashMap<String, String>)
-> StdResult<(), Error>;
}
}
@@ -223,15 +224,18 @@ mod api {
use self::api::*;
struct OpenVpnEventApiImpl<L>
- where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static
+ where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static
{
on_event: L,
}
impl<L> OpenVpnEventApi for OpenVpnEventApiImpl<L>
- where L: Fn(OpenVpnPluginEvent, OpenVpnEnv) + Send + Sync + 'static
+ where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static
{
- fn openvpn_event(&self, event: OpenVpnPluginEvent, env: OpenVpnEnv) -> StdResult<(), Error> {
+ fn openvpn_event(&self,
+ event: OpenVpnPluginEvent,
+ env: HashMap<String, String>)
+ -> StdResult<(), Error> {
debug!("OpenVPN event {:?}", event);
(self.on_event)(event, env);
Ok(())
diff --git a/talpid-openvpn-plugin/Cargo.toml b/talpid-openvpn-plugin/Cargo.toml
index c2ae39430c..e0b4ddec77 100644
--- a/talpid-openvpn-plugin/Cargo.toml
+++ b/talpid-openvpn-plugin/Cargo.toml
@@ -12,5 +12,5 @@ error-chain = "0.10"
log = "0.3"
env_logger = "0.4"
+openvpn-plugin = { version = "0.2", features = ["serialize", "log"] }
talpid-ipc = { path = "../talpid-ipc" }
-openvpn-ffi = { path = "../openvpn-ffi" }
diff --git a/talpid-openvpn-plugin/src/lib.rs b/talpid-openvpn-plugin/src/lib.rs
index 55102d111c..5bb8bece64 100644
--- a/talpid-openvpn-plugin/src/lib.rs
+++ b/talpid-openvpn-plugin/src/lib.rs
@@ -4,16 +4,15 @@ extern crate error_chain;
extern crate log;
extern crate env_logger;
-extern crate openvpn_ffi;
+#[macro_use]
+extern crate openvpn_plugin;
extern crate talpid_ipc;
-use std::os::raw::{c_int, c_void};
+use openvpn_plugin::types::{EventResult, OpenVpnPluginEvent};
+use std::collections::HashMap;
+use std::ffi::CString;
mod processing;
-
-use openvpn_ffi::{OPENVPN_PLUGIN_FUNC_ERROR, OPENVPN_PLUGIN_FUNC_SUCCESS, OpenVpnPluginEvent,
- openvpn_plugin_args_func_in, openvpn_plugin_args_func_return,
- openvpn_plugin_args_open_in, openvpn_plugin_args_open_return};
use processing::EventProcessor;
@@ -43,117 +42,51 @@ error_chain!{
pub static INTERESTING_EVENTS: &'static [OpenVpnPluginEvent] =
&[OpenVpnPluginEvent::Up, OpenVpnPluginEvent::RoutePredown];
+openvpn_plugin!(
+ ::openvpn_open,
+ ::openvpn_close,
+ ::openvpn_event,
+ ::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 openvpn_plugin_args_open_in,
- retptr: *mut openvpn_plugin_args_open_return)
- -> c_int {
- if init_logger().is_err() {
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
- match openvpn_plugin_open_v3_internal(args, retptr) {
- Ok(_) => OPENVPN_PLUGIN_FUNC_SUCCESS,
- Err(e) => {
- log_error("Unable to initialize plugin", &e);
- OPENVPN_PLUGIN_FUNC_ERROR
- }
- }
-}
-
-fn openvpn_plugin_open_v3_internal(args: *const openvpn_plugin_args_open_in,
- retptr: *mut openvpn_plugin_args_open_return)
- -> Result<()> {
+fn openvpn_open(args: &[CString],
+ _env: &HashMap<CString, CString>)
+ -> Result<(Vec<OpenVpnPluginEvent>, EventProcessor)> {
+ env_logger::init().chain_err(|| "Failed to bootstrap logging system")?;
debug!("Initializing plugin");
+
let core_server_id = parse_args(args)?;
+ info!("Connecting back to talpid core at {}", core_server_id);
let processor = EventProcessor::new(core_server_id).chain_err(|| ErrorKind::InitHandleFailed)?;
- unsafe {
- (*retptr).type_mask = openvpn_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(Box::new(processor)) as *const c_void;
- }
- Ok(())
+
+ Ok((INTERESTING_EVENTS.to_vec(), processor))
}
-fn parse_args(args: *const openvpn_plugin_args_open_in) -> Result<talpid_ipc::IpcServerId> {
- let mut args_iter = unsafe { openvpn_ffi::parse::string_array((*args).argv) }
+fn parse_args(args: &[CString]) -> Result<talpid_ipc::IpcServerId> {
+ let mut args_iter = openvpn_plugin::ffi::parse::string_array_utf8(args)
.chain_err(|| ErrorKind::ParseArgsFailed)?
.into_iter();
let _plugin_path = args_iter.next();
- let core_server_id: String = args_iter.next()
+ let core_server_id: talpid_ipc::IpcServerId = args_iter.next()
.ok_or_else(|| 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`
-#[no_mangle]
-pub extern "C" fn openvpn_plugin_close_v1(handle: *const c_void) {
+fn openvpn_close(_handle: EventProcessor) {
debug!("Unloading plugin");
- // 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 {
- match openvpn_plugin_func_v3_internal(args) {
- Ok(_) => OPENVPN_PLUGIN_FUNC_SUCCESS,
- Err(e) => {
- log_error("Error while processing event", &e);
- 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)?;
+fn openvpn_event(event: OpenVpnPluginEvent,
+ _args: &[CString],
+ env: &HashMap<CString, CString>,
+ handle: &mut EventProcessor)
+ -> Result<EventResult> {
debug!("Received event: {:?}", event);
- let env = unsafe { openvpn_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).chain_err(|| ErrorKind::EventProcessingFailed)?;
- // Convert the handle back to a raw pointer to not deallocate it when we return.
- Box::into_raw(handle);
-
- Ok(())
-}
+ let parsed_env = openvpn_plugin::ffi::parse::env_utf8(env)
+ .chain_err(|| ErrorKind::ParseEnvFailed)?;
-
-pub fn init_logger() -> ::std::result::Result<(), ()> {
- env_logger::init().or_else(
- |e| {
- use std::io::Write;
- let mut stderr = ::std::io::stderr();
- writeln!(&mut stderr, "Unable to initialize logging: {}", e)
- .expect("Unable to write to stderr");
- Err(())
- },
- )
-}
-
-pub fn log_error(msg: &str, error: &Error) {
- error!("{}", msg);
- for e in error.iter() {
- error!("caused by: {}", e);
- }
- // When running with RUST_BACKTRACE=1, print backtrace.
- if let Some(backtrace) = error.backtrace() {
- error!("backtrace: {:?}", backtrace);
- }
+ handle.process_event(event, parsed_env).chain_err(|| ErrorKind::EventProcessingFailed)?;
+ Ok(EventResult::Success)
}
diff --git a/talpid-openvpn-plugin/src/processing.rs b/talpid-openvpn-plugin/src/processing.rs
index e33097c633..5f3c8e4afd 100644
--- a/talpid-openvpn-plugin/src/processing.rs
+++ b/talpid-openvpn-plugin/src/processing.rs
@@ -1,5 +1,5 @@
-use openvpn_ffi;
-
+use openvpn_plugin;
+use std::collections::HashMap;
use talpid_ipc::{IpcServerId, WsIpcClient};
error_chain! {
@@ -18,14 +18,14 @@ pub struct EventProcessor {
impl EventProcessor {
pub fn new(server_id: IpcServerId) -> Result<EventProcessor> {
- debug!("Creating EventProcessor");
+ trace!("Creating EventProcessor");
let ipc_client = WsIpcClient::new(server_id).chain_err(|| "Unable to create IPC client")?;
Ok(EventProcessor { ipc_client })
}
pub fn process_event(&mut self,
- event: openvpn_ffi::OpenVpnPluginEvent,
- env: openvpn_ffi::OpenVpnEnv)
+ event: openvpn_plugin::types::OpenVpnPluginEvent,
+ env: HashMap<String, String>)
-> Result<()> {
trace!("Processing \"{:?}\" event", event);
self.ipc_client
@@ -34,10 +34,3 @@ impl EventProcessor {
.chain_err(|| ErrorKind::IpcSendingError)
}
}
-
-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.
- debug!("Dropping EventProcessor");
- }
-}