summaryrefslogtreecommitdiffhomepage
path: root/talpid-openvpn-plugin/src/lib.rs
blob: 71c332a212d0912dead1834b0ac8fa6d54b053a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! # License
//!
//! Copyright (C) 2017  Amagicom AB
//!
//! This program is free software: you can redistribute it and/or modify it under the terms of the
//! GNU General Public License as published by the Free Software Foundation, either version 3 of
//! the License, or (at your option) any later version.

extern crate env_logger;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate log;

#[macro_use]
extern crate openvpn_plugin;
extern crate talpid_ipc;

use openvpn_plugin::types::{EventResult, OpenVpnPluginEvent};
use std::collections::HashMap;
use std::ffi::CString;

mod processing;
use processing::EventProcessor;


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")
        }
        ParseArgsFailed {
            description("Unable to parse arguments from OpenVPN")
        }
        EventProcessingFailed {
            description("Failed to process the event")
        }
    }
}


/// 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];

openvpn_plugin!(
    ::openvpn_open,
    ::openvpn_close,
    ::openvpn_event,
    ::EventProcessor
);

fn openvpn_open(
    args: Vec<CString>,
    _env: HashMap<CString, CString>,
) -> Result<(Vec<OpenVpnPluginEvent>, EventProcessor)> {
    env_logger::init();
    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)?;

    Ok((INTERESTING_EVENTS.to_vec(), processor))
}

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: 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)
}


fn openvpn_close(_handle: EventProcessor) {
    debug!("Unloading plugin");
}

fn openvpn_event(
    event: OpenVpnPluginEvent,
    _args: Vec<CString>,
    env: HashMap<CString, CString>,
    handle: &mut EventProcessor,
) -> Result<EventResult> {
    debug!("Received event: {:?}", event);

    let parsed_env =
        openvpn_plugin::ffi::parse::env_utf8(&env).chain_err(|| ErrorKind::ParseEnvFailed)?;

    handle
        .process_event(event, parsed_env)
        .chain_err(|| ErrorKind::EventProcessingFailed)?;
    Ok(EventResult::Success)
}