summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Jiung <jiung.yu@samsung.com>2017-03-02 11:07:12 +0900
committerchleun.moon <chleun.moon@samsung.com>2017-03-02 14:39:20 +0900
commit7859b3f51163cdb798423679bf291ffe27eff988 (patch)
tree83d3e24652bbf766b8a03dc929fe68aad0578dbb
parent376f28aa4b82ec003c8579968ba42ff3050b10c5 (diff)
downloadconnman-7859b3f51163cdb798423679bf291ffe27eff988.tar.gz
connman-7859b3f51163cdb798423679bf291ffe27eff988.tar.bz2
connman-7859b3f51163cdb798423679bf291ffe27eff988.zip
Add code to parse section struct into vici request
Change-Id: If19978b75ab53c43a641a5e51bb0ef6a2adaa545 Signed-off-by: Yu jiung <jiung.yu@samsung.com>
-rwxr-xr-xMakefile.plugins2
-rwxr-xr-xconfigure.ac2
-rw-r--r--doc/vpn-config-format.txt29
-rwxr-xr-xpackaging/connman.spec4
-rw-r--r--vpn/plugins/ipsec.c203
-rw-r--r--vpn/plugins/ipsec.h6
-rw-r--r--vpn/plugins/vici-client.c525
-rw-r--r--vpn/plugins/vici-client.h37
8 files changed, 656 insertions, 152 deletions
diff --git a/Makefile.plugins b/Makefile.plugins
index c8ae2d15..e1c0a11c 100755
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -119,7 +119,7 @@ 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.c vpn/plugins/vici-client.c
vpn_plugins_ipsec_la_CFLAGS = $(plugin_cflags) -DIPSEC=\"@IPSEC@\" \
-DVPN_STATEDIR=\""$(vpn_statedir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\"
diff --git a/configure.ac b/configure.ac
index bd711405..95aa0a4f 100755
--- a/configure.ac
+++ b/configure.ac
@@ -115,7 +115,7 @@ AC_ARG_ENABLE(ipsec,
[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)
+ AC_PATH_PROG(IPSEC, [charon], [/usr/bin/charon], $PATH:/usr/bin)
if (test -z "${IPSEC}"); then
AC_MSG_ERROR(ipsec binary not found)
fi
diff --git a/doc/vpn-config-format.txt b/doc/vpn-config-format.txt
index 23c9c149..15d3a261 100644
--- a/doc/vpn-config-format.txt
+++ b/doc/vpn-config-format.txt
@@ -195,6 +195,35 @@ PPTP VPN supports following options (see pptp(8) and pppd(8) for details)
PPPD.RequirMPPEStateful mppe-stateful Allow MPPE to use stateful mode (O)
PPPD.NoVJ no-vj-comp No Van Jacobson compression (O)
+IPsec VPN supports following options (see swanctl.conf(5) for details):
+ Option name IPSec config value Description
+ IPsec.Version Version IKE major version to use for connection (M)
+ IPsec.LeftAddrs local_addrs Local address(es) to use for IKE communication (M)
+ IPsec.RightAddrs remote_addrs Remote address(es) to use for IKE communication (M)
+
+
+ IPsec.LocalAuth local.auth Authentication to perform locally (M)
+ IPsec.LocalCerts local.certs Certificate candidate to use for authentication (O)
+ IPsec.LocalID local.id IKE identity to use for authentication round (O)
+ IPsec.LocalXauthID local.xauth_id Client XAuth username used in the XAuth exchange (O)
+ IPsec.LocalXauthAuth local-xauth.auth Xauth round authentication to perform locally (O)
+ IPsec.LocalXauthXauthID local-xauth.xauth_id Xauth round client XAuth username used in the XAuth exchange (O)
+
+ IPsec.RemoteAuth remote.auth Authentication to expect from remote (M)
+ IPsec.RemoteCerts remote.certs Certificate candidate to use for authentication (O)
+ IPsec.RemoteID remote.id IKE identity to use for authentication round (O)
+ IPsec.RemoteXauthAuth remote-xauth.auth Xauth round authentication to expect from remote (O)
+ IPsec.ChildrenLocalTs children.local_ts local selectors to include in CHILD_SA (O)
+ IPsec.ChildrenRemoteTs children.remote_ts Remote selectors to include in CHILD_SA (O)
+
+ IPsec.IkeData secret.data IKE PSK raw shared key data
+ IPsec.IkeOwners secret.Owners list of shared key owner identities
+ IPsec.XauthData secret.data XAUTH raw shared key data
+ IPsec.XauthOwners secret.Owners list of shared key owner identities
+
+ IPsec.CertType cert.type certificate type, X509|X509_AC|X509_CRL
+ IPsec.CertFlag cert.flag X.509 certificate flag, NONE|CA|AA|OCSP
+ IPsec.CertData cert.data PEM or DER encoded certificate data
Example
=======
diff --git a/packaging/connman.spec b/packaging/connman.spec
index 9923a4d1..2b7dfd42 100755
--- a/packaging/connman.spec
+++ b/packaging/connman.spec
@@ -70,9 +70,9 @@ OpenVPN support for Connman.
%if %{with connman_ipsec}
%package plugin-ipsec
-Summary: Openvpn Support for Connman
+Summary: IPsec Support for Connman
Requires: %{name} = %{version}
-Requires: ipsec
+Requires: strongswan
%description plugin-ipsec
OpenVPN support for Connman.
diff --git a/vpn/plugins/ipsec.c b/vpn/plugins/ipsec.c
index 7cf0a5ce..de66cea7 100644
--- a/vpn/plugins/ipsec.c
+++ b/vpn/plugins/ipsec.c
@@ -50,26 +50,37 @@ static DBusConnection *connection;
struct {
const char *cm_opt;
const char *vici_key;
- const char *section;
+ const char *subsection;
+ vici_section_add_element add_elem;
} 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.Version", "version", NULL, vici_section_add_kv},
+ {"IPsec.LeftAddrs", "local_addrs", NULL, vici_section_add_kvl},
+ {"IPsec.RightAddrs", "remote_addrs", NULL, vici_section_add_kvl},
+
+ {"IPsec.LocalAuth", "auth", "local", vici_section_add_kv},
+ {"IPsec.LocalCerts", "certs", "local", vici_section_add_kv},
+ {"IPsec.LocalID", "id", "local", vici_section_add_kv},
+ {"IPsec.LocalXauthID", "xauth_id", "local", vici_section_add_kv},
+ {"IPsec.LocalXauthAuth", "auth", "local-xauth", vici_section_add_kv},
+ {"IPsec.LocalXauthXauthID", "xauth_id", "local-xauth", vici_section_add_kv},
+ {"IPsec.RemoteAuth", "auth", "remote", vici_section_add_kv},
+ {"IPsec.RemoteCerts", "certs", "remote", vici_section_add_kv},
+ {"IPsec.RemoteID", "id", "remote", vici_section_add_kv},
+ {"IPsec.RemoteXauthID", "xauth_id", "remote", vici_section_add_kv},
+ {"IPsec.RemoteXauthAuth", "auth", "remote-xauth", vici_section_add_kv},
+ {"IPsec.RemoteXauthXauthID", "xauth_id", "remote-xauth", vici_section_add_kv},
+ {"IPsec.ChildrenLocalTs", "local_ts", "children", vici_section_add_kvl},
+ {"IPsec.ChildrenRemoteTs", "remote_ts", "children", vici_section_add_kvl},
};
-/*
- * 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"},
+ {"IPsec.IkeData", "data"},
+ {"IPsec.IkeOwners", "owners"},
+ {"IPsec.XauthData", "data"},
+ {"IPsec.XauthOwners", "owners"},
};
struct {
@@ -77,9 +88,9 @@ struct {
const char *vici_type;
const char *vici_flag;
} ipsec_cert_options[] = {
- {"IPsec.LocalCert", "X509", NULL},
- {"IPsec.RemoteCert", "X509", NULL},
- {"IPsec.CACert", "X509", "CA"},
+ {"IPsec.CertType", "type", NULL},
+ {"IPsec.CertFlag", "flag", NULL},
+ {"IPsec.CertData", "data", NULL},
};
@@ -88,85 +99,6 @@ 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)
@@ -176,11 +108,11 @@ static int ipsec_is_same_auth(const char* req, const char* target)
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);
+ VICISection *sect;
+ sect = vici_create_section(NULL);
+ vici_section_add_kv(sect, "type", type, NULL);
+ vici_section_add_kv(sect, "flag", flag, NULL);
+ vici_section_add_kv(sect, "data", data, NULL);
vici_client_send_request(VICI_REQUEST_LOAD_CERT, sect);
@@ -194,7 +126,7 @@ static int ipsec_load_conn(struct vpn_provider *provider)
const char *key;
const char *value;
const char *subsection;
- struct section *sect;
+ VICISection *sect;
int i;
value = vpn_provider_get_string(provider, "Name");
@@ -203,8 +135,8 @@ static int ipsec_load_conn(struct vpn_provider *provider)
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);
+ subsection = ipsec_conn_options[i].subsection;
+ ipsec_conn_options[i].add_elem(sect, key, value, subsection);
}
vici_client_send_request(VICI_REQUEST_LOAD_CONN, sect);
@@ -214,33 +146,49 @@ static int ipsec_load_conn(struct vpn_provider *provider)
return 0;
}
-static int ipsec_load_shared(struct vpn_provider *provider)
+static int ipsec_load_shared_psk(struct vpn_provider *provider)
{
- const char *type;
const char *data;
const char *owner;
- const char *auth_type;
- struct section *sect;
+ VICISection *sect;
- sect = vici_create_section("");
+ data = vpn_provider_get_string(provider, "IPsec.IkeData");
+ owner = vpn_provider_get_string(provider, "IPsec.IkeOwners");
- 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;
- }
+ if (!data)
+ return 0;
- owner = vpn_provider_get_string(provider, "IPsec.LocalXauthID");
+ sect = vici_create_section(NULL);
- 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_section_add_kv(sect, "type", VICI_SHARED_TYPE_PSK, NULL);
+ vici_section_add_kv(sect, "data", data, NULL);
+ vici_section_add_kvl(sect, "owners", owner, NULL);
+
+ vici_client_send_request(VICI_REQUEST_LOAD_SHARED, sect);
+
+ vici_destroy_section(sect);
+
+ return 0;
+}
+
+
+static int ipsec_load_shared_xauth(struct vpn_provider *provider)
+{
+ const char *data;
+ const char *owner;
+ VICISection *sect;
+
+ data = vpn_provider_get_string(provider, "IPsec.XauthData");
+ owner = vpn_provider_get_string(provider, "IPsec.XauthOwners");
+
+ if (!data)
+ return 0;
+
+ sect = vici_create_section(NULL);
+
+ vici_section_add_kv(sect, "type", VICI_SHARED_TYPE_XAUTH, NULL);
+ vici_section_add_kv(sect, "data", data, NULL);
+ vici_section_add_kvl(sect, "owners", owner, NULL);
vici_client_send_request(VICI_REQUEST_LOAD_SHARED, sect);
@@ -300,12 +248,17 @@ static int ipsec_connect(struct vpn_provider *provider,
IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed");
/*
- * Send the load-shared command for PSK or XAUTH
+ * Send the load-shared command for PSK
*/
- err = ipsec_load_shared(provider);
+ err = ipsec_load_shared_psk(provider);
IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
/*
+ * Send the load-shared command for XAUTH
+ */
+ err = ipsec_load_shared_xauth(provider);
+ IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
+ /*
* Send the load-cert command
*/
err = ipsec_load_cert(provider);
diff --git a/vpn/plugins/ipsec.h b/vpn/plugins/ipsec.h
index b9c146da..0081a439 100644
--- a/vpn/plugins/ipsec.h
+++ b/vpn/plugins/ipsec.h
@@ -30,10 +30,4 @@
} \
} 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
index e4cfa9a7..dbf14084 100644
--- a/vpn/plugins/vici-client.c
+++ b/vpn/plugins/vici-client.c
@@ -1,46 +1,541 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
#include <glib.h>
#include <connman/log.h>
#include "ipsec.h"
#include "vici-client.h"
+#define VICI_DEFAULT_URI "/var/run/charon.vici"
+
+#define SOCK_FD_MIN 3
+#define VICI_REQUEST_TIMEOUT 5000
+
+enum vici_element {
+ VICI_END = 0,
+ VICI_SECTION_START = 1,
+ VICI_SECTION_END = 2,
+ VICI_KEY_VALUE = 3,
+ VICI_LIST_START = 4,
+ VICI_LIST_ITEM = 5,
+ VICI_LIST_END = 6,
+};
+
+enum vici_packet_type {
+ VICI_CMD_REQUEST = 0,
+ VICI_CMD_RESPONSE = 1,
+ VICI_CMD_UNKNOWN = 2,
+ VICI_EVENT_REGISTER = 3,
+ VICI_EVENT_UNREGISTER = 4,
+ VICI_EVENT_CONFIRM = 5,
+ VICI_EVENT_UNKNOWN = 6,
+ VICI_EVENT = 7,
+};
+
+typedef void (*process_return)(unsigned char *buf, unsigned int size);
+
struct request {
+ unsigned int allocated;
+ unsigned int used;
+ unsigned int hdr_len;
+ char *buf;
+ int err;
+ int client_source_idle_id;
+ int client_source_timeout_id;
+ /* process reply */
+ unsigned int rcv_pkt_size;
+ process_return handler;
+ /* davici_cb cb; */
+ void *user;
};
-static struct request* vici_client_create_request(struct section* root)
+struct _VICIClient {
+ /* io data */
+ int client_sock;
+ int client_watch;
+ GList *request_list;
+};
+
+struct _VICISection {
+ char *name;
+ GHashTable *kvs;
+ GHashTable *kvls;
+ GHashTable *subsection;
+};
+
+static void _remove_list(gpointer data)
+{
+ if (data == NULL)
+ return;
+
+ g_slist_free_full((GSList *)data, g_free);
+}
+
+void vici_destroy_section(VICISection* section)
+{
+ g_free(section->name);
+ g_hash_table_destroy(section->kvs);
+ g_hash_table_destroy(section->kvls);
+ g_hash_table_destroy(section->subsection);
+ g_free(section);
+}
+
+static void _free_section(gpointer data)
+{
+ VICISection* section = (VICISection*)data;
+ vici_destroy_section(section);
+}
+
+VICISection* vici_create_section(const char* name)
{
- struct request* req;
+ VICISection* section;
- req = g_try_new0(struct req, 1);
- if (!req) {
- comman_error("Failed to create request");
+ section = g_try_new0(VICISection, 1);
+ if (!section) {
+ connman_error("Failed to create section");
return NULL;
}
- return req;
+ if (name)
+ section->name = g_strdup(name);
+ section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _remove_list);
+ section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _free_section);
+ return section;
}
-static int vici_client_send_command(struct request* req)
+static int _vici_section_add_kvl(VICISection* section, const char* key, const char* value)
{
+ GSList *list = NULL;
+ if (section == NULL || key == NULL || value == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ list = g_hash_table_lookup(section->kvls, key);
+ if (list == NULL) {
+ list = g_slist_alloc();
+ g_hash_table_insert(section->kvls, g_strdup(key), list);
+ }
+
+ list = g_slist_prepend(list, g_strdup(value));
+
return 0;
}
-int vici_client_initialize()
+static int _vici_section_add_kv(VICISection* section, const char* key, const char* value)
{
- /*
- * Open socket to connect vici plugin
- */
+ if (section == NULL || key == NULL || value == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
return 0;
}
-int vici_client_deinitialize()
+static int vici_section_add_subsection(VICISection* section, const char* name, VICISection* child)
{
+ if (section == NULL || name == NULL || child == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ g_hash_table_insert(section->subsection, g_strdup(name), child);
return 0;
}
-int vici_client_send_request(const char* cmd, struct section* root)
+static VICISection* _vici_section_get_subsection(VICISection* section, const char* name)
{
- struct request* req = vici_client_send_request(root);
- vici_client_send_command(req);
+ VICISection* sub = g_hash_table_lookup(section->subsection, name);
+ if (sub == NULL) {
+ sub = vici_create_section(name);
+ vici_section_add_subsection(section, name, sub);
+ }
+ return sub;
+}
+
+int vici_section_add_kv(VICISection* section, const char* key,
+ const char* value, const char* subsection)
+{
+ VICISection* target = section;
+
+ if (section == NULL || key == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ if (subsection)
+ target = _vici_section_get_subsection(section, subsection);
+
+ _vici_section_add_kv(target, key, value);
+ return 0;
+}
+
+int vici_section_add_kvl(VICISection* section, const char* key,
+ const char* value, const char* subsection)
+{
+ VICISection* target = section;
+
+ if (section == NULL || key == NULL) {
+ connman_error("invalid parameter");
+ return -1;
+ }
+
+ if (subsection)
+ target = _vici_section_get_subsection(section, subsection);
+
+ _vici_section_add_kvl(target, key, value);
+ return 0;
+}
+
+static void* _add_element(struct request *r, enum vici_element type,
+ unsigned int size)
+{
+ unsigned int newlen;
+ void *ret, *new;
+
+ if (r->used + size + 1 > r->allocated)
+ {
+ newlen = r->allocated;
+ while (newlen < r->used + size + 1)
+ {
+ newlen *= 2;
+ }
+ new = realloc(r->buf, newlen);
+ if (!new)
+ {
+ r->err = -errno;
+ return NULL;
+ }
+ r->buf = new;
+ r->allocated = newlen;
+ }
+ r->buf[r->used++] = type;
+ ret = r->buf + r->used;
+ r->used += size;
+ return ret;
+}
+
+static void vici_section_start(struct request *r, const char *name)
+{
+ uint8_t nlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = _add_element(r, VICI_SECTION_START, 1 + nlen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ }
+}
+
+static void vici_section_end(struct request *r)
+{
+ _add_element(r, VICI_SECTION_END, 0);
+}
+
+static void vici_kv(struct request *r, const char *name,
+ const void *buf, unsigned int buflen)
+{
+ uint8_t nlen;
+ uint16_t vlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = _add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ vlen = htons(buflen);
+ memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
+ memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
+ }
+}
+
+
+static void vici_list_start(struct request *r, const char *name)
+{
+ uint8_t nlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = _add_element(r, VICI_LIST_START, 1 + nlen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ }
+}
+
+static void vici_list_item(struct request *r, const void *buf,
+ unsigned int buflen)
+{
+ uint16_t vlen;
+ char *pos;
+
+ pos = _add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
+ if (pos)
+ {
+ vlen = htons(buflen);
+ memcpy(pos, &vlen, sizeof(vlen));
+ memcpy(pos + sizeof(vlen), buf, buflen);
+ }
+}
+
+static void vici_list_end(struct request *r)
+{
+ _add_element(r, VICI_LIST_END, 0);
+}
+
+
+static int create_vici_request(enum vici_packet_type type, const char *name,
+ struct request **rp)
+{
+ struct request *req = NULL;
+
+ if (!name || !rp)
+ return -1;
+
+ req = g_try_new0(struct request, 1);
+ if (!req)
+ return -1;
+
+ req->used = 2;
+ req->used += strlen(name);
+ req->allocated = MIN(32, req->used);
+ req->buf = g_try_new0(char, req->allocated);
+ if (!req->buf) {
+ g_free(req);
+ return -1;
+ }
+
+ req->buf[0] = type;
+ req->buf[1] = req->used - 2; /* except for type and name length */
+ memcpy(req->buf + 2, name, req->used - 2);
+ req->hdr_len = req->used;
+
+ *rp = req;
+
+ return 0;
+}
+
+static void write_section_kvs(VICISection *section, struct request *req)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (section == NULL || req == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, section->kvs);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!key || !value)
+ continue;
+ vici_kv(req, (const char*)key, (const void *)value, strlen((char *)value));
+ }
+
+ return;
+}
+
+static void _write_vl(gpointer data, gpointer user_data)
+{
+ struct request *req = NULL;
+ char *value = NULL;
+
+ if (!data || !user_data)
+ return;
+
+ value = (char *)data;
+ req = (struct request *)user_data;
+ vici_list_item(req, value, strlen(value));
+
+ return;
+}
+
+static void write_section_kvls(VICISection *section, struct request *req)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (section == NULL || req == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, section->kvls);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!key || !value)
+ continue;
+
+ vici_list_start(req, key);
+ g_slist_foreach((GSList *)value, (GFunc)_write_vl, (gpointer)req);
+ vici_list_end(req);
+ }
+
+ return;
+}
+
+static void _write_section(struct request *req, VICISection *section)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ VICISection *subsection;
+
+ if (req == NULL || section == NULL)
+ return;
+
+ if (section->name)
+ vici_section_start(req, section->name);
+
+ write_section_kvs(section, req);
+ write_section_kvls(section, req);
+
+ g_hash_table_iter_init(&iter, section->subsection);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!key || !value)
+ continue;
+ subsection = value;
+ _write_section(req, subsection);
+ }
+
+ if (section->name)
+ vici_section_end(req);
+ return;
+}
+
+static int vici_client_send_command(struct request *req)
+{
+ return 0;
+}
+
+static int destroy_vici_request(struct request *req)
+{
+ return 0;
+}
+
+int vici_client_send_request(const char *cmd, VICISection *root)
+{
+ struct request* req = NULL;
+ int ret;
+
+ ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
+ if (ret < 0) {
+ connman_error("error on create_request\n");
+ return -1;
+ }
+
+ _write_section(req, root);
+
+ ret = vici_client_send_command(req);
+ if (ret < 0) {
+ connman_error("error on send_command\n");
+ return -1;
+ }
+
+ ret = destroy_vici_request(req);
+ if (ret < 0) {
+ connman_error("error on destroy_request \n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int str_to_sock_addr(const char *uri, struct sockaddr_un *addr)
+{
+ memset(addr, 0, sizeof(*addr));
+ addr->sun_family = AF_UNIX;
+ strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
+
+ addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
+
+ return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
+}
+
+static int connect_sock(const char *uri)
+{
+ struct sockaddr_un addr;
+ int len, fd;
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -errno;
+
+ len = str_to_sock_addr(uri, &addr);
+ if (len == -1)
+ {
+ close(fd);
+ return -1;
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
+ close(fd);
+ return -errno;
+ }
+
+ return fd;
+}
+
+static gboolean process_reply(GIOChannel *source, GIOChannel condtion, gpointer user_data)
+{
+ return TRUE;
+}
+int vici_client_initialize()
+{
+ GIOChannel *vici_channel;
+ VICIClient *vici_client = NULL;
+
+ vici_client = g_try_new0(VICIClient, 1);
+ if (!vici_client) {
+ return VICI_CLIENT_ERROR_NOMEM;
+ }
+
+ vici_client->client_sock = connect_sock(VICI_DEFAULT_URI);
+ if (vici_client->client_sock < 0) {
+ g_free(vici_client);
+ return -EIO;
+ }
+
+ vici_channel = g_io_channel_unix_new(vici_client->client_sock);
+ if (!vici_channel) {
+ close(vici_client->client_sock);
+ g_free(vici_client);
+ }
+
+ vici_client->client_watch = g_io_add_watch_full(vici_channel,
+ G_PRIORITY_LOW,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc)process_reply,
+ (gpointer)vici_client,
+ NULL);
+ g_io_channel_unref(vici_channel);
+
+ return 0;
+}
+
+int vici_client_deinitialize()
+{
+ VICIClient *vici_client = NULL;
+
+ if (vici_client->client_watch > 0) {
+ g_source_remove(vici_client->client_watch);
+ vici_client->client_watch = 0;
+ }
+
+ close(vici_client->client_sock);
+ g_free(vici_client);
+
return 0;
}
diff --git a/vpn/plugins/vici-client.h b/vpn/plugins/vici-client.h
index 3a60f313..a49f0a78 100644
--- a/vpn/plugins/vici-client.h
+++ b/vpn/plugins/vici-client.h
@@ -1,14 +1,47 @@
#ifndef __VICI_CLIENT_H
#define __VICI_CLIENT_H
-#define VICI_DEFAULT_URI "/var/run/charon.vici"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* strongswan VICI plugin client part*/
+struct _VICIClient;
+typedef struct _VICIClient VICIClient;
+
+struct _VICISection;
+typedef struct _VICISection VICISection;
+
+typedef enum {
+ VICI_CLIENT_ERROR_NONE,
+ VICI_CLIENT_ERROR_NOMEM,
+} VICIClientError;
+
+typedef enum {
+ VICI_CLIENT_EVENT,
+} VICIClientEvent;
#define VICI_REQUEST_LOAD_CONN "load-conn"
#define VICI_REQUEST_LOAD_SHARED "load-shared"
#define VICI_REQUEST_LOAD_CERT "load-cert"
+#define VICI_REQUEST_LOAD_INITIATE "initiate"
+
+typedef int (*vici_section_add_element)(VICISection *sect, const char *key,
+ const char *value, const char *subsection);
+
+VICISection* vici_create_section(const char *name);
+int vici_section_add_kv(VICISection *sect, const char *key,
+ const char *value, const char *subsection);
+int vici_section_add_kvl(VICISection *sect, const char *key,
+ const char *value, const char *subsection);
+void vici_destroy_section(VICISection *sect);
int vici_client_initialize();
int vici_client_deinitialize();
-int vici_client_send_request(const char* cmd, struct section* root);
+int vici_client_send_request(const char *cmd, VICISection *root);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __VICI_CLIENT_H */