summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchleun.moon <chleun.moon@samsung.com>2017-02-24 05:36:58 (GMT)
committerchleun.moon <chleun.moon@samsung.com>2017-02-24 07:29:51 (GMT)
commit376f28aa4b82ec003c8579968ba42ff3050b10c5 (patch)
treeb94301abb0de0d4aa3ba95394ec6806ef4606439
parent21e92ee0e2531e80b5bda990a99bbe72abf31991 (diff)
downloadconnman-376f28aa4b82ec003c8579968ba42ff3050b10c5.zip
connman-376f28aa4b82ec003c8579968ba42ff3050b10c5.tar.gz
connman-376f28aa4b82ec003c8579968ba42ff3050b10c5.tar.bz2
Add ipsec pluginrefs/changes/76/116376/4
Change-Id: Iafe144233e8dd8bc066e00340a5853e4e16d925a Signed-off-by: cheoleun <chleun.moon@samsung.com>
-rwxr-xr-xMakefile.am1
-rwxr-xr-xMakefile.plugins25
-rwxr-xr-xconfigure.ac21
-rwxr-xr-xpackaging/connman.spec25
-rwxr-xr-xscripts/ipsec-script.c146
-rw-r--r--vpn/plugins/ipsec.c363
-rw-r--r--vpn/plugins/ipsec.h39
-rw-r--r--vpn/plugins/vici-client.c46
-rw-r--r--vpn/plugins/vici-client.h14
9 files changed, 680 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index dd2474c..e287363 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -407,6 +407,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles \
--enable-hh2serial-gps \
--enable-openconnect \
--enable-openvpn \
+ --enable-ipsec \
--enable-vpnc \
--enable-session-policy-local \
--enable-nmcompat \
diff --git a/Makefile.plugins b/Makefile.plugins
index 83ad8fb..c8ae2d1 100755
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -108,6 +108,25 @@ vpn_plugins_openvpn_la_LDFLAGS = $(plugin_ldflags)
endif
endif
+if IPSEC
+if IPSEC_BUILTIN
+builtin_vpn_modules += ipsec
+builtin_vpn_sources += vpn/plugins/ipsec.h vpn/plugins/ipsec.c
+builtin_vpn_sources += vpn/plugins/vici-client.h vpn/plugins/vici-client.c
+builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h
+builtin_vpn_cflags += -DIPSEC=\"@IPSEC@\"
+else
+vpn_plugin_LTLIBRARIES += vpn/plugins/ipsec.la
+vpn_plugin_objects += $(plugins_ipsec_la_OBJECTS)
+vpn_plugins_ipsec_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \
+ vpn/plugins/ipsec.c
+vpn_plugins_ipsec_la_CFLAGS = $(plugin_cflags) -DIPSEC=\"@IPSEC@\" \
+ -DVPN_STATEDIR=\""$(vpn_statedir)"\" \
+ -DSCRIPTDIR=\""$(build_scriptdir)"\"
+vpn_plugins_ipsec_la_LDFLAGS = $(plugin_ldflags)
+endif
+endif
+
if VPNC
if VPNC_BUILTIN
builtin_vpn_modules += vpnc
@@ -225,6 +244,12 @@ script_PROGRAMS += scripts/openvpn-script
scripts_openvpn_script_LDADD = @DBUS_LIBS@
endif
+if IPSEC
+script_PROGRAMS += scripts/ipsec-script
+
+scripts_ipsec_script_LDADD = @DBUS_LIBS@
+endif
+
if NMCOMPAT
builtin_modules += nmcompat
builtin_sources += plugins/nmcompat.c
diff --git a/configure.ac b/configure.ac
index e765625..bd71140 100755
--- a/configure.ac
+++ b/configure.ac
@@ -107,6 +107,26 @@ fi
AM_CONDITIONAL(OPENVPN, test "${enable_openvpn}" != "no")
AM_CONDITIONAL(OPENVPN_BUILTIN, test "${enable_openvpn}" = "builtin")
+AC_ARG_WITH(ipsec, AC_HELP_STRING([--with-ipsec=PROGRAM],
+ [specify location of ipsec binary]), [path_ipsec=${withval}])
+
+AC_ARG_ENABLE(ipsec,
+ AC_HELP_STRING([--enable-ipsec], [enable ipsec support]),
+ [enable_ipsec=${enableval}], [enable_ipsec="no"])
+if (test "${enable_ipsec}" != "no"); then
+ if (test -z "${path_ipsec}"); then
+ AC_PATH_PROG(IPSEC, [ipsec], [], $PATH:/sbin:/usr/sbin)
+ if (test -z "${IPSEC}"); then
+ AC_MSG_ERROR(ipsec binary not found)
+ fi
+ else
+ IPSEC="${path_ipsec}"
+ AC_SUBST(IPSEC)
+ fi
+fi
+AM_CONDITIONAL(IPSEC, test "${enable_ipsec}" != "no")
+AM_CONDITIONAL(IPSEC_BUILTIN, test "${enable_ipsec}" = "builtin")
+
AC_ARG_WITH(vpnc, AC_HELP_STRING([--with-vpnc=PROGRAM],
[specify location of vpnc binary]), [path_vpnc=${withval}])
@@ -402,6 +422,7 @@ fi
AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no" -o \
"${enable_openvpn}" != "no" -o \
+ "${enable_ipsec}" != "no" -o \
"${enable_vpnc}" != "no" -o \
"${enable_l2tp}" != "no" -o \
"${enable_pptp}" != "no")
diff --git a/packaging/connman.spec b/packaging/connman.spec
index b2e1d6a..9923a4d 100755
--- a/packaging/connman.spec
+++ b/packaging/connman.spec
@@ -1,5 +1,6 @@
%bcond_with connman_openconnect
%bcond_without connman_openvpn
+%bcond_without connman_ipsec
%bcond_without connman_vpnd
Name: connman
@@ -24,6 +25,9 @@ BuildRequires: openconnect
%if %{with connman_openvpn}
BuildRequires: openvpn
%endif
+%if %{with connman_ipsec}
+BuildRequires: strongswan
+%endif
BuildRequires: ca-certificates-devel
BuildRequires: readline-devel
#%systemd_requires
@@ -64,6 +68,16 @@ Requires: openvpn
OpenVPN support for Connman.
%endif
+%if %{with connman_ipsec}
+%package plugin-ipsec
+Summary: Openvpn Support for Connman
+Requires: %{name} = %{version}
+Requires: ipsec
+
+%description plugin-ipsec
+OpenVPN support for Connman.
+%endif
+
%if %{with connman_vpnd}
%package connman-vpnd
Summary: VPN Support for Connman
@@ -136,6 +150,9 @@ chmod +x bootstrap
%if %{with connman_openvpn}
--enable-openvpn \
%endif
+%if %{with connman_ipsec}
+ --enable-ipsec \
+%endif
%if 0%{?enable_connman_features}
%connman_features \
%endif
@@ -274,6 +291,14 @@ systemctl daemon-reload
%{_datadir}/dbus-1/system-services/net.connman.vpn.service
%endif
+%if %{with connman_ipsec}
+%files plugin-ipsec
+%manifest %{name}.manifest
+%{_libdir}/%{name}/plugins-vpn/ipsec.so
+%{_libdir}/%{name}/scripts/ipsec-script
+%{_datadir}/dbus-1/system-services/net.connman.vpn.service
+%endif
+
%if %{with connman_vpnd}
%files connman-vpnd
%manifest %{name}.manifest
diff --git a/scripts/ipsec-script.c b/scripts/ipsec-script.c
new file mode 100755
index 0000000..6ba0d29
--- /dev/null
+++ b/scripts/ipsec-script.c
@@ -0,0 +1,146 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
+ * Copyright (C) 2010,2012-2014 BMW Car IT GmbH.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <libgen.h>
+
+#include <dbus/dbus.h>
+
+extern char **environ;
+
+static void print(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsyslog(LOG_INFO, format, ap);
+ va_end(ap);
+}
+
+static void append(DBusMessageIter *dict, const char *pattern)
+{
+ DBusMessageIter entry;
+ const char *key, *value;
+ char *delim;
+
+ delim = strchr(pattern, '=');
+ *delim = '\0';
+
+ key = pattern;
+ value = delim + 1;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+int main(int argc, char *argv[])
+{
+ DBusConnection *conn;
+ DBusError error;
+ DBusMessage *msg;
+ DBusMessageIter iter, dict;
+ char **envp, *busname, *interface, *path, *reason;
+ int ret = 0;
+
+ openlog(basename(argv[0]), LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+ busname = getenv("CONNMAN_BUSNAME");
+ interface = getenv("CONNMAN_INTERFACE");
+ path = getenv("CONNMAN_PATH");
+
+ reason = getenv("script_type");
+
+ if (!busname || !interface || !path || !reason) {
+ print("Required environment variables not set; "
+ "bus=%s iface=%s path=%s reason=%s",
+ busname, interface, path, reason);
+ ret = 1;
+ goto out;
+ }
+ dbus_error_init(&error);
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (!conn) {
+ if (dbus_error_is_set(&error)) {
+ print("%s", error.message);
+ dbus_error_free(&error);
+ } else
+ print("Failed to get on system bus");
+
+ goto out;
+ }
+
+ msg = dbus_message_new_method_call(busname, path,
+ interface, "notify");
+ if (!msg) {
+ dbus_connection_unref(conn);
+ print("Failed to allocate method call");
+ goto out;
+ }
+
+ dbus_message_set_no_reply(msg, TRUE);
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ for (envp = environ; envp && *envp; envp++)
+ append(&dict, *envp);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ if (!dbus_connection_send(conn, msg, NULL)) {
+ print("Failed to send message");
+ goto out;
+ }
+
+ dbus_connection_flush(conn);
+
+ dbus_message_unref(msg);
+
+ dbus_connection_unref(conn);
+
+out:
+ closelog();
+
+ return ret;
+}
diff --git a/vpn/plugins/ipsec.c b/vpn/plugins/ipsec.c
new file mode 100644
index 0000000..7cf0a5c
--- /dev/null
+++ b/vpn/plugins/ipsec.c
@@ -0,0 +1,363 @@
+/*
+ *
+ * ConnMan VPN daemon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <net/if.h>
+
+#include <glib.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/plugin.h>
+#include <connman/log.h>
+#include <connman/task.h>
+#include <connman/dbus.h>
+#include <connman/ipconfig.h>
+
+#include "../vpn-provider.h"
+
+#include "vpn.h"
+#include "ipsec.h"
+#include "vici-client.h"
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+static DBusConnection *connection;
+
+struct {
+ const char *cm_opt;
+ const char *vici_key;
+ const char *section;
+} ipsec_conn_options[] = {
+ {"IPsec.Version", "version", NULL},
+ {"IPsec.LocalAddrs", "local_addrs", NULL},
+ {"IPsec.RemoteAddrs", "remote_addrs", NULL},
+ {"IPsec.LocalAuth", "auth", "local"},
+ {"IPsec.RemoteAuth", "auth", "remote"},
+};
+
+/*
+ * IPsec.LocalID
+ * IPsec.RemoteTS
+ */
+struct {
+ const char *cm_opt;
+ const char *vici_type;
+} ipsec_shared_options[] = {
+ {"IPsec.LocalXauthID", NULL},
+ {"IPsec.XauthSecret", "XAUTH"},
+ {"IPsec.IKESecret", "IKE"},
+};
+
+struct {
+ const char *cm_opt;
+ const char *vici_type;
+ const char *vici_flag;
+} ipsec_cert_options[] = {
+ {"IPsec.LocalCert", "X509", NULL},
+ {"IPsec.RemoteCert", "X509", NULL},
+ {"IPsec.CACert", "X509", "CA"},
+};
+
+
+static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider)
+{
+ return 0;
+}
+
+static void vici_destroy_section(struct section* sect)
+{
+ g_hash_table_destroy(sect->elm);
+ g_hash_table_destroy(sect->subsection);
+ g_free(sect);
+}
+
+static void free_section(gpointer data)
+{
+ struct section* sect = (struct section*)data;
+ vici_destroy_section(sect);
+}
+
+static struct section* vici_create_section(const char* name)
+{
+ struct section* sect;
+
+ sect = g_try_new0(struct section, 1);
+ if (!sect) {
+ connman_error("Failed to create section");
+ return NULL;
+ }
+
+ sect->name = g_strdup(name);
+ sect->elm = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ sect->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section);
+ return sect;
+}
+
+static int vici_section_add_kv(struct section* sect, const char* key, const char* value)
+{
+ if (sect == NULL || key == NULL || value == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ g_hash_table_insert(sect->elm, g_strdup(key), g_strdup(value));
+ return 0;
+}
+
+static int vici_section_add_subsection(struct section* sect, const char* name, struct section* child)
+{
+ if (sect == NULL || name == NULL || child == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ g_hash_table_insert(sect->subsection, g_strdup(name), child);
+ return 0;
+}
+
+
+static struct section* vici_section_get_subsection(struct section* sect, const char* name)
+{
+ struct section* sub = g_hash_table_lookup(sect->subsection, name);
+ if (sub == NULL) {
+ sub = vici_create_section(name);
+ vici_section_add_subsection(sect, name, sub);
+ }
+ return sub;
+}
+
+static int vici_section_add_element(struct section* sect, const char* key,
+ const char* value, const char* subsection)
+{
+ struct section* target = sect;
+
+ if (sect == NULL || key == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ if (subsection)
+ target = vici_section_get_subsection(sect, subsection);
+
+ vici_section_add_kv(target, key, value);
+ return 0;
+}
+
+static int ipsec_is_same_auth(const char* req, const char* target)
+{
+ if (req == NULL || target == NULL)
+ return 0;
+ return (g_strcmp0(req, target) == 0);
+}
+
+static int vici_load_cert(const char* type, const char* flag, const char* data)
+{
+ struct section *sect;
+ sect = vici_create_section("");
+ vici_section_add_element(sect, "type", type, NULL);
+ vici_section_add_element(sect, "flag", flag, NULL);
+ vici_section_add_element(sect, "data", data, NULL);
+
+ vici_client_send_request(VICI_REQUEST_LOAD_CERT, sect);
+
+ vici_destroy_section(sect);
+
+ return 0;
+}
+
+static int ipsec_load_conn(struct vpn_provider *provider)
+{
+ const char *key;
+ const char *value;
+ const char *subsection;
+ struct section *sect;
+ int i;
+
+ value = vpn_provider_get_string(provider, "Name");
+ sect = vici_create_section(value);
+
+ for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) {
+ key = ipsec_conn_options[i].vici_key;
+ value = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt);
+ subsection = ipsec_conn_options[i].section;
+ vici_section_add_element(sect, key, value, subsection);
+ }
+
+ vici_client_send_request(VICI_REQUEST_LOAD_CONN, sect);
+
+ vici_destroy_section(sect);
+
+ return 0;
+}
+
+static int ipsec_load_shared(struct vpn_provider *provider)
+{
+ const char *type;
+ const char *data;
+ const char *owner;
+ const char *auth_type;
+ struct section *sect;
+
+ sect = vici_create_section("");
+
+ auth_type = vpn_provider_get_string(provider, "IPsec.LocalAuth");
+ if (ipsec_is_same_auth(auth_type, IPSEC_AUTH_PSK)) {
+ type = VICI_SHARED_TYPE_PSK;
+ data = vpn_provider_get_string(provider, "IPsec.IKESecret");
+ } else if (ipsec_is_same_auth(auth_type, IPSEC_AUTH_XAUTH)) {
+ type = VICI_SHARED_TYPE_XAUTH;
+ data = vpn_provider_get_string(provider, "IPsec.XauthSecret");
+ } else {
+ connman_error("invalid auth type: %s", auth_type);
+ return -1;
+ }
+
+ owner = vpn_provider_get_string(provider, "IPsec.LocalXauthID");
+
+ vici_section_add_element(sect, "type", type, NULL);
+ vici_section_add_element(sect, "data", data, NULL);
+ vici_section_add_element(sect, "owner", owner, NULL);
+
+ vici_client_send_request(VICI_REQUEST_LOAD_SHARED, sect);
+
+ vici_destroy_section(sect);
+
+ return 0;
+}
+
+static int ipsec_load_cert(struct vpn_provider *provider)
+{
+ const char *type;
+ const char *flag;
+ const char *data;
+ const char *auth_type;
+ int i;
+
+ auth_type = vpn_provider_get_string(provider, "IPsec.LocalAuth");
+ if (!ipsec_is_same_auth(auth_type, IPSEC_AUTH_RSA)) {
+ connman_error("invalid auth type: %s", auth_type);
+ return -1;
+ }
+
+ for (i = 0; i < (int)ARRAY_SIZE(ipsec_cert_options); i++) {
+ type = ipsec_cert_options[i].vici_type;;
+ flag = ipsec_cert_options[i].vici_flag;
+ data = vpn_provider_get_string(provider, ipsec_cert_options[i].cm_opt);
+ vici_load_cert(type, flag, data);
+ }
+
+ return 0;
+}
+
+static int ipsec_connect(struct vpn_provider *provider,
+ struct connman_task *task, const char *if_name,
+ vpn_provider_connect_cb_t cb, const char *dbus_sender,
+ void *user_data)
+{
+ int err = 0;
+
+ /*
+ * Start charon daemon using ipsec script of strongSwan.
+ */
+ connman_task_add_argument(task, "start", NULL);
+ err = connman_task_run(task, vpn_died, provider, NULL, NULL, NULL);
+ IPSEC_ERROR_CHECK_GOTO(err, done, "ipsec start failed");
+
+ /*
+ * Initialize vici client
+ */
+ err = vici_client_initialize();
+ IPSEC_ERROR_CHECK_GOTO(err, done, "failed to initialize vici_client");
+
+ /*
+ * Send the load-conn command
+ */
+ err = ipsec_load_conn(provider);
+ IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed");
+
+ /*
+ * Send the load-shared command for PSK or XAUTH
+ */
+ err = ipsec_load_shared(provider);
+ IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
+
+ /*
+ * Send the load-cert command
+ */
+ err = ipsec_load_cert(provider);
+ IPSEC_ERROR_CHECK_GOTO(err, done, "load-cert failed");
+
+done:
+ if (cb)
+ cb(provider, user_data, err);
+
+ return err;
+}
+
+static int ipsec_error_code(struct vpn_provider *provider, int exit_code)
+{
+ return 0;
+}
+
+static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile)
+{
+ return 0;
+}
+
+static void ipsec_disconnect(struct vpn_provider *provider)
+{
+ int err = 0;
+
+ err = vici_client_deinitialize();
+ IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client");
+}
+
+static struct vpn_driver vpn_driver = {
+ .flags = VPN_FLAG_NO_TUN,
+ .notify = ipsec_notify,
+ .connect = ipsec_connect,
+ .error_code = ipsec_error_code,
+ .save = ipsec_save,
+ .disconnect = ipsec_disconnect,
+};
+
+static int ipsec_init(void)
+{
+ connection = connman_dbus_get_connection();
+
+ return vpn_register("ipsec", &vpn_driver, IPSEC);
+}
+
+static void ipsec_exit(void)
+{
+ vpn_unregister("ipsec");
+
+ dbus_connection_unref(connection);
+}
+
+CONNMAN_PLUGIN_DEFINE(ipsec, "IPSec plugin", VERSION,
+ CONNMAN_PLUGIN_PRIORITY_DEFAULT, ipsec_init, ipsec_exit)
diff --git a/vpn/plugins/ipsec.h b/vpn/plugins/ipsec.h
new file mode 100644
index 0000000..b9c146d
--- /dev/null
+++ b/vpn/plugins/ipsec.h
@@ -0,0 +1,39 @@
+#ifndef __CONNMAN_VPND_PLUGIN_IPSEC_H
+#define __CONNMAN_VPND_PLUGIN_IPSEC_H
+
+#define IPSEC_AUTH_PSK "PSK"
+#define IPSEC_AUTH_RSA "RSA"
+#define IPSEC_AUTH_XAUTH "XAUTH"
+
+#define VICI_SHARED_TYPE_PSK "IKE"
+#define VICI_SHARED_TYPE_XAUTH "XAUTH"
+
+#define IPSEC_ERROR_CHECK_GOTO(err, target, fmt, arg...) do { \
+ if (err < 0) { \
+ connman_error(fmt, ## arg); \
+ err = -1; \
+ goto target; \
+ } \
+} while (0)
+
+#define IPSEC_ERROR_CHECK_RETURN(err, fmt, arg...) do { \
+ if (err < 0) { \
+ connman_error(fmt, ## arg); \
+ return; \
+ } \
+} while (0)
+
+#define IPSEC_ERROR_CHECK_RETURN_VAL(err, ret, fmt, arg...) do { \
+ if (err < 0) { \
+ connman_error(fmt, ## arg); \
+ return ret; \
+ } \
+} while (0)
+
+struct section {
+ const char *name;
+ GHashTable *elm;
+ GHashTable *subsection;
+};
+
+#endif /* __CONNMAN_VPND_PLUGIN_IPSEC_H */
diff --git a/vpn/plugins/vici-client.c b/vpn/plugins/vici-client.c
new file mode 100644
index 0000000..e4cfa9a
--- /dev/null
+++ b/vpn/plugins/vici-client.c
@@ -0,0 +1,46 @@
+#include <glib.h>
+
+#include <connman/log.h>
+#include "ipsec.h"
+#include "vici-client.h"
+
+struct request {
+};
+
+static struct request* vici_client_create_request(struct section* root)
+{
+ struct request* req;
+
+ req = g_try_new0(struct req, 1);
+ if (!req) {
+ comman_error("Failed to create request");
+ return NULL;
+ }
+
+ return req;
+}
+
+static int vici_client_send_command(struct request* req)
+{
+ return 0;
+}
+
+int vici_client_initialize()
+{
+ /*
+ * Open socket to connect vici plugin
+ */
+ return 0;
+}
+
+int vici_client_deinitialize()
+{
+ return 0;
+}
+
+int vici_client_send_request(const char* cmd, struct section* root)
+{
+ struct request* req = vici_client_send_request(root);
+ vici_client_send_command(req);
+ return 0;
+}
diff --git a/vpn/plugins/vici-client.h b/vpn/plugins/vici-client.h
new file mode 100644
index 0000000..3a60f31
--- /dev/null
+++ b/vpn/plugins/vici-client.h
@@ -0,0 +1,14 @@
+#ifndef __VICI_CLIENT_H
+#define __VICI_CLIENT_H
+
+#define VICI_DEFAULT_URI "/var/run/charon.vici"
+
+#define VICI_REQUEST_LOAD_CONN "load-conn"
+#define VICI_REQUEST_LOAD_SHARED "load-shared"
+#define VICI_REQUEST_LOAD_CERT "load-cert"
+
+int vici_client_initialize();
+int vici_client_deinitialize();
+int vici_client_send_request(const char* cmd, struct section* root);
+
+#endif /* __VICI_CLIENT_H */