diff options
author | Yu Jiung <jiung.yu@samsung.com> | 2017-03-02 11:07:12 +0900 |
---|---|---|
committer | chleun.moon <chleun.moon@samsung.com> | 2017-03-02 14:39:20 +0900 |
commit | 7859b3f51163cdb798423679bf291ffe27eff988 (patch) | |
tree | 83d3e24652bbf766b8a03dc929fe68aad0578dbb | |
parent | 376f28aa4b82ec003c8579968ba42ff3050b10c5 (diff) | |
download | connman-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-x | Makefile.plugins | 2 | ||||
-rwxr-xr-x | configure.ac | 2 | ||||
-rw-r--r-- | doc/vpn-config-format.txt | 29 | ||||
-rwxr-xr-x | packaging/connman.spec | 4 | ||||
-rw-r--r-- | vpn/plugins/ipsec.c | 203 | ||||
-rw-r--r-- | vpn/plugins/ipsec.h | 6 | ||||
-rw-r--r-- | vpn/plugins/vici-client.c | 525 | ||||
-rw-r--r-- | vpn/plugins/vici-client.h | 37 |
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 */ |