From 6a5fcbfe10fdf0d8db9fe439229d82e0ce1e5edd Mon Sep 17 00:00:00 2001 From: "taesub.kim" Date: Thu, 21 Jan 2016 16:54:44 +0900 Subject: [PATCH] Default VPN CAPI Initial Code (without Connman Library) Change-Id: I59aa5bcfcb35184cd099b04cfa9fed0ee5e7469d Signed-off-by: Taesub Kim --- AUTHORS | 2 + CMakeLists.txt | 98 ++ ChangeLog | 3 + LICENSE.APLv2 | 202 +++++ NOTICE | 3 + capi-network-vpn.pc.in | 13 + dvpnlib/include/debug.h | 27 + dvpnlib/include/dvpnlib-common.h | 54 ++ dvpnlib/include/dvpnlib-internal.h | 75 ++ dvpnlib/include/dvpnlib-vpn-connection.h | 149 ++++ dvpnlib/include/dvpnlib-vpn-manager.h | 55 ++ dvpnlib/include/dvpnlib-vpn.h | 15 + dvpnlib/src/dvpnlib-vpn-connnection.c | 1039 ++++++++++++++++++++++ dvpnlib/src/dvpnlib-vpn-manager.c | 321 +++++++ dvpnlib/src/dvpnlib-vpn.c | 33 + dvpnlib/src/dvpnlib.c | 180 ++++ include/vpn.h | 381 ++++++++ packaging/capi-network-vpn.manifest | 5 + packaging/capi-network-vpn.spec | 70 ++ src/include/common.h | 57 ++ src/include/vpn-internal.h | 83 ++ src/vpn-internal.c | 417 +++++++++ src/vpn.c | 388 ++++++++ test/CMakeLists.txt | 20 + test/vpn_test.c | 456 ++++++++++ 25 files changed, 4146 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 ChangeLog create mode 100644 LICENSE.APLv2 create mode 100644 NOTICE create mode 100644 capi-network-vpn.pc.in create mode 100644 dvpnlib/include/debug.h create mode 100644 dvpnlib/include/dvpnlib-common.h create mode 100644 dvpnlib/include/dvpnlib-internal.h create mode 100644 dvpnlib/include/dvpnlib-vpn-connection.h create mode 100644 dvpnlib/include/dvpnlib-vpn-manager.h create mode 100644 dvpnlib/include/dvpnlib-vpn.h create mode 100644 dvpnlib/src/dvpnlib-vpn-connnection.c create mode 100644 dvpnlib/src/dvpnlib-vpn-manager.c create mode 100644 dvpnlib/src/dvpnlib-vpn.c create mode 100644 dvpnlib/src/dvpnlib.c create mode 100644 include/vpn.h create mode 100644 packaging/capi-network-vpn.manifest create mode 100644 packaging/capi-network-vpn.spec create mode 100644 src/include/common.h create mode 100644 src/include/vpn-internal.h create mode 100644 src/vpn-internal.c create mode 100644 src/vpn.c create mode 100644 test/CMakeLists.txt create mode 100644 test/vpn_test.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..8e0097f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Sushil Kumar Yadav +Sushil diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a98ed96 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,98 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(fw_name "capi-network-vpn") + +PROJECT(${fw_name}) + +SET(CMAKE_INSTALL_PREFIX /usr) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +SET(INC_DIR include dvpnlib/include/) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/${INC_DIR}/) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/include/) + + +SET(dependents "dlog vconf capi-base-common glib-2.0 gio-2.0") +SET(pc_dependents "capi-base-common") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_name} REQUIRED ${dependents}) +FOREACH(flag ${${fw_name}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror -fvisibility=hidden") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DTIZEN_DEBUG") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") + +aux_source_directory(src SOURCES) +aux_source_directory(dvpnlib/src DVPNLIB_SOURCES) +ADD_LIBRARY(${fw_name} SHARED ${SOURCES} ${DVPNLIB_SOURCES}) + +TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS}) + +SET_TARGET_PROPERTIES(${fw_name} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 +) + +INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL( + DIRECTORY ${INC_DIR}/ DESTINATION include/network + FILES_MATCHING + PATTERN "*_private.h" EXCLUDE + PATTERN "${INC_DIR}/*.h" + ) + +SET(PC_NAME ${fw_name}) +SET(PC_REQUIRED ${pc_dependents}) +SET(PC_LDFLAGS -l${fw_name}) + +CONFIGURE_FILE( + ${fw_name}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +ADD_SUBDIRECTORY(test) + +IF(UNIX) + +ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) +ADD_CUSTOM_COMMAND( + DEPENDS clean + COMMENT "distribution clean" + COMMAND find + ARGS . + -not -name config.cmake -and \( + -name tester.c -or + -name Testing -or + -name CMakeFiles -or + -name cmake.depends -or + -name cmake.check_depends -or + -name CMakeCache.txt -or + -name cmake.check_cache -or + -name *.cmake -or + -name Makefile -or + -name core -or + -name core.* -or + -name gmon.out -or + -name install_manifest.txt -or + -name *.pc -or + -name *~ \) + | grep -v TC | xargs rm -rf + TARGET distclean + VERBATIM +) + +ENDIF(UNIX) diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..30df408 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,3 @@ +Ver 0.1: + Added Default VPN CAPI Code + diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..0e0f016 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/capi-network-vpn.pc.in b/capi-network-vpn.pc.in new file mode 100644 index 0000000..ee6db75 --- /dev/null +++ b/capi-network-vpn.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=/usr/lib +includedir=/usr/include/network + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} diff --git a/dvpnlib/include/debug.h b/dvpnlib/include/debug.h new file mode 100644 index 0000000..c4c1a24 --- /dev/null +++ b/dvpnlib/include/debug.h @@ -0,0 +1,27 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include + +#ifndef RELEASE + +#include + +#undef LOG_TAG +#define LOG_TAG "DVPN_LIB" + +#define DBG(fmt, arg...) SLOGD(fmt, ##arg) + +#define WARN(fmt, arg...) SLOGI(fmt, ##arg) + +#define ERROR(fmt, arg...) SLOGE(fmt, ##arg) + +#else + +#define DBG(fmt, arg...) +#define WARN(fmt, arg...) +#define ERROR(fmt, arg...) + +#endif + +#endif diff --git a/dvpnlib/include/dvpnlib-common.h b/dvpnlib/include/dvpnlib-common.h new file mode 100644 index 0000000..f2af6da --- /dev/null +++ b/dvpnlib/include/dvpnlib-common.h @@ -0,0 +1,54 @@ +#ifndef __COMMON_LIB_H__ +#define __COMMON_LIB_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum dvpnlib_err { + /* Successful */ + DVPNLIB_ERR_NONE = 0, + /* General error */ + DVPNLIB_ERR_FAILED, + /* Specific error */ + DVPNLIB_ERR_OPERATION_FAILED, + DVPNLIB_ERR_INVALID_PARAMETER, + DVPNLIB_ERR_PERMISSION_DENIED, + DVPNLIB_ERR_PASSPHRASE_REQUIRED, + DVPNLIB_ERR_NOT_REGISTERED, + DVPNLIB_ERR_NOT_UNIQUE, + DVPNLIB_ERR_NOT_SUPPORTED, + DVPNLIB_ERR_NOT_IMPLEMENTED, + DVPNLIB_ERR_NOT_FOUND, + DVPNLIB_ERR_NOT_CARRIER, + DVPNLIB_ERR_IN_PROGRESS, + DVPNLIB_ERR_ALREADY_EXISTS, + DVPNLIB_ERR_ALREADY_ENABLED, + DVPNLIB_ERR_ALREADY_DISABLED, + DVPNLIB_ERR_ALREADY_CONNECTED, + DVPNLIB_ERR_NOT_CONNECTED, + DVPNLIB_ERR_OPERATION_ABORTED, + DVPNLIB_ERR_OPERATION_TIMEOUT, + DVPNLIB_ERR_INVALID_SERVICE, + DVPNLIB_ERR_INVALID_PROPERTY, + /* D-Bus error */ + DVPNLIB_ERR_TIMEOUT, + DVPNLIB_ERR_UNKNOWN_PROPERTY, + DVPNLIB_ERR_PROPERTY_READONLY, + DVPNLIB_ERR_UNKNOWN_METHOD, +}; + +/* + * Common + */ +typedef void(*dvpnlib_reply_cb)(enum dvpnlib_err result, + void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvpnlib/include/dvpnlib-internal.h b/dvpnlib/include/dvpnlib-internal.h new file mode 100644 index 0000000..1d0ef75 --- /dev/null +++ b/dvpnlib/include/dvpnlib-internal.h @@ -0,0 +1,75 @@ +#ifndef __DVPNLIB_INTERNAL_H__ +#define __DVPNLIB_INTERNAL_H__ + +#include +#include + +#include "debug.h" +#include "dvpnlib-common.h" + +struct vpn_manager; +struct vpn_connection; + +extern struct vpn_manager *vpn_manager; + +#define VPN_NAME "net.connman.vpn" +#define VPN_MANAGER_INTERFACE "net.connman.vpn.Manager" +#define VPN_CONNECTION_INTERFACE "net.connman.vpn.Connection" +#define VPN_MANAGER_PATH "/" + +struct common_reply_data { + void *cb; + void *data; + void *user; + bool flag; /*TODO: */ +}; + +struct error_map_t { + const gchar *error_key_str; + enum dvpnlib_err type; +}; + +/* + * D-Bus + */ +enum dvpnlib_err common_set_property(GDBusProxy *dbus_proxy, + const char *property, + GVariant *value); +GVariant *common_get_call_method_result(GDBusProxy *dbus_proxy, + const char *method); +enum dvpnlib_err common_set_interface_call_method_sync( + GDBusProxy *dbus_proxy, + const char *method, + GVariant **parameters); +enum dvpnlib_err common_set_interface_call_method(GDBusProxy *dbus_proxy, + const char *method, + GVariant **parameters, + GAsyncReadyCallback callback, + gpointer user_data); + +/* + * VPN Manager + */ +struct vpn_manager *create_vpn_manager(void); +void free_vpn_manager(struct vpn_manager *manager); +GDBusProxy *get_vpn_manager_dbus_proxy(void); + +/* + * VPN Connection + */ +void sync_vpn_connections(void); +void destroy_vpn_connections(void); +struct vpn_connection *get_connection_by_path(const gchar *path); +gboolean add_vpn_connection(GVariant **parameters, + struct vpn_connection **connection); +void remove_vpn_connection(struct vpn_connection *connection); + +struct common_reply_data *common_reply_data_new(void *cb, + void *data, + void *user, bool flag); +/* + * Error + */ +enum dvpnlib_err get_error_type(GError *error); + +#endif diff --git a/dvpnlib/include/dvpnlib-vpn-connection.h b/dvpnlib/include/dvpnlib-vpn-connection.h new file mode 100644 index 0000000..20682ea --- /dev/null +++ b/dvpnlib/include/dvpnlib-vpn-connection.h @@ -0,0 +1,149 @@ +#ifndef __VPN_CONNECTION_H__ +#define __VPN_CONNECTION_H__ + +#include "dvpnlib-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct vpn_connection; + +enum vpn_connection_state { + VPN_CONN_STATE_IDLE, + VPN_CONN_STATE_READY, + VPN_CONN_STATE_CONFIGURATION, + VPN_CONN_STATE_DISCONNECT, + VPN_CONN_STATE_FAILURE, + VPN_CONN_STATE_UNKNOWN, +}; + +enum vpn_connection_property_type { + VPN_CONN_PROP_NONE, + + /*string State [readonly]*/ + VPN_CONN_PROP_STATE, + /*string Name [readonly]*/ + VPN_CONN_PROP_NAME, + /*boolean Immutable [readonly]*/ + VPN_CONN_PROP_IMMUTABLE, + + /*string Domain [readonly]*/ + VPN_CONN_PROP_DOMAIN, + /*string Host [readonly]*/ + VPN_CONN_PROP_HOST, + /*string Type [readonly]*/ + VPN_CONN_PROP_TYPE, + /*int Index [readonly]*/ + VPN_CONN_PROP_INDEX, + /*dict IPv4 [readonly]*/ + VPN_CONN_PROP_IPV4, + /*dict IPv6 [readonly]*/ + VPN_CONN_PROP_IPV6, + /*array{string} Nameservers [readonly]*/ + VPN_CONN_PROP_NAMESERVERS, + /* array{dict} UserRoutes [readwrite] */ + VPN_CONN_PROP_USERROUTES, + /* array{dict} ServerRoutes [readonly] */ + VPN_CONN_PROP_SERVERROUTES, +}; + +/* + * Connection Property Structures + */ +struct vpn_connection_ipv4 { + gchar *address; + gchar *netmask; + gchar *gateway; + gchar *peer; +}; + +struct vpn_connection_ipv6 { + gchar *address; + gchar *prefix_length; + gchar *gateway; + gchar *peer; +}; + +struct vpn_connection_route { + int protocol_family; + gchar *network; + gchar *netmask; + gchar *gateway; +}; + +/* + * Callback prototype + */ +typedef void (*vpn_connection_property_changed_cb)( + struct vpn_connection *connection, + void *user_data); + +/* +* Methods +*/ +/* experimental */ +GList *vpn_get_connections(void); +struct vpn_connection *vpn_get_connection( + const char *host, const char *domain); +enum dvpnlib_err vpn_connection_clear_property( + struct vpn_connection *connection); +enum dvpnlib_err vpn_connection_connect(struct vpn_connection *connection, + dvpnlib_reply_cb callback, + void *user_data); +enum dvpnlib_err +vpn_connection_disconnect(struct vpn_connection *connection); + +/* + * Properties + */ +/* Set */ +enum dvpnlib_err +vpn_connection_set_user_routes(struct vpn_connection *connection, + struct vpn_connection_route **user_routes); + +/* Get */ +const char *vpn_connection_get_type( + struct vpn_connection *connection); +const char *vpn_connection_get_name( + struct vpn_connection *connection); +const char *vpn_connection_get_path( + struct vpn_connection *connection); +const char *vpn_connection_get_domain( + struct vpn_connection *connection); +const char *vpn_connection_get_host( + struct vpn_connection *connection); +bool vpn_connection_get_immutable( + struct vpn_connection *connection); +int vpn_connection_get_index( + struct vpn_connection *connection); + +enum vpn_connection_state vpn_connection_get_state( + struct vpn_connection *connection); +const struct vpn_connection_ipv4 *vpn_connection_get_ipv4( + struct vpn_connection *connection); +const struct vpn_connection_ipv6 *vpn_connection_get_ipv6( + struct vpn_connection *connection); +char **vpn_connection_get_nameservers( + struct vpn_connection *connection); +GSList *vpn_connection_get_user_routes( + struct vpn_connection *connection); +GSList *vpn_connection_get_server_routes( + struct vpn_connection *connection); +/* + * Signals + */ +enum dvpnlib_err vpn_connection_set_property_changed_cb( + struct vpn_connection *connection, + enum vpn_connection_property_type type, + vpn_connection_property_changed_cb cb, + void *user_data); +enum dvpnlib_err vpn_connection_unset_property_changed_cb( + struct vpn_connection *connection, + enum vpn_connection_property_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvpnlib/include/dvpnlib-vpn-manager.h b/dvpnlib/include/dvpnlib-vpn-manager.h new file mode 100644 index 0000000..2af716e --- /dev/null +++ b/dvpnlib/include/dvpnlib-vpn-manager.h @@ -0,0 +1,55 @@ +#ifndef __VPN_MANAGER_H__ +#define __VPN_MANAGER_H__ + +#include "dvpnlib-common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct vpn_manager; +struct vpn_connection; + +struct vpn_setting_entry { + gchar *key; + gchar *value; +}; + +/* + * Callback prototype + */ +typedef void (*vpn_connection_added_cb)( + struct vpn_connection *connection, + void *user_data); +typedef void (*vpn_connection_removed_cb)( + struct vpn_connection *connection, + void *user_data); +/* +* Methods +*/ +GList *vpn_get_connections(void); +enum dvpnlib_err dvpnlib_vpn_manager_create(GHashTable *settings, + dvpnlib_reply_cb callback, + void *user_data); +enum dvpnlib_err dvpnlib_vpn_manager_remove(const char *path, + dvpnlib_reply_cb callback, + void *user_data); +enum dvpnlib_err dvpnlib_vpn_manager_register_agent(const char *path); +enum dvpnlib_err dvpnlib_vpn_manager_unregister_agent(const char *path); + +/* + * Signals + */ +void dvpnlib_vpn_manager_set_connection_added_cb( + vpn_connection_added_cb cb, + void *user_data); +void dvpnlib_vpn_manager_unset_connection_added_cb(); +void dvpnlib_vpn_manager_set_connection_removed_cb( + vpn_connection_removed_cb cb, + void *user_data); +void dvpnlib_vpn_manager_unset_connection_removed_cb(); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvpnlib/include/dvpnlib-vpn.h b/dvpnlib/include/dvpnlib-vpn.h new file mode 100644 index 0000000..a8aede8 --- /dev/null +++ b/dvpnlib/include/dvpnlib-vpn.h @@ -0,0 +1,15 @@ +#ifndef __VPN_LIB_H__ +#define __VPN_LIB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int dvpnlib_vpn_init(void); +void dvpnlib_vpn_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dvpnlib/src/dvpnlib-vpn-connnection.c b/dvpnlib/src/dvpnlib-vpn-connnection.c new file mode 100644 index 0000000..88e93bb --- /dev/null +++ b/dvpnlib/src/dvpnlib-vpn-connnection.c @@ -0,0 +1,1039 @@ +#include "dvpnlib-internal.h" +#include "dvpnlib-vpn-connection.h" + +static GList *vpn_connection_list; +static GHashTable *vpn_connection_hash; + +struct connection_property_changed_cb { + vpn_connection_property_changed_cb property_changed_cb; + void *user_data; +}; + +struct vpn_connection { + GDBusProxy *dbus_proxy; + gchar *type; + gchar *path; + gchar *name; + gchar *domain; + gchar *host; + gboolean immutable; + gint index; + enum vpn_connection_state state; + struct vpn_connection_ipv4 *ipv4; + struct vpn_connection_ipv6 *ipv6; + gchar **nameservers; + GSList *user_routes; /*struct vpn_connection_route */ + GSList *server_routes; /* struct vpn_connection_route */ + GHashTable *property_changed_cb_hash; +}; + +static void free_vpn_connection_ipv4(struct vpn_connection_ipv4 *ipv4_info); +static void free_vpn_connection_ipv6(struct vpn_connection_ipv6 *ipv6_info); +static void free_vpn_connection_route(gpointer data); + +enum dvpnlib_err +vpn_connection_set_user_routes(struct vpn_connection *connection, + struct vpn_connection_route **user_routes) +{ + if (!connection || !user_routes) + return DVPNLIB_ERR_INVALID_PARAMETER; + + GVariantBuilder user_routes_b; + GVariant *user_routes_v; + + g_variant_builder_init(&user_routes_b, G_VARIANT_TYPE("a(a{sv})")); + + while (*user_routes != NULL) { + + g_variant_builder_open(&user_routes_b, + G_VARIANT_TYPE("(a{sv})")); + g_variant_builder_open(&user_routes_b, + G_VARIANT_TYPE("a{sv}")); + + if ((*user_routes)->protocol_family) { + g_variant_builder_add(&user_routes_b, "{sv}", + "ProtocolFamily", + g_variant_new_int32( + (*user_routes)->protocol_family)); + } + + if ((*user_routes)->network) { + g_variant_builder_add(&user_routes_b, "{sv}", + "Network", + g_variant_new_string((*user_routes)->network)); + } + + if ((*user_routes)->netmask) { + g_variant_builder_add(&user_routes_b, "{sv}", + "Netmask", + g_variant_new_string((*user_routes)->netmask)); + } + + if ((*user_routes)->gateway) { + g_variant_builder_add(&user_routes_b, "{sv}", + "Gateway", + g_variant_new_string((*user_routes)->gateway)); + } + + g_variant_builder_close(&user_routes_b); + g_variant_builder_close(&user_routes_b); + + user_routes++; + } + + user_routes_v = g_variant_builder_end(&user_routes_b); + + return common_set_property(connection->dbus_proxy, "UserRoutes", + user_routes_v); + +} + +static struct connection_property_changed_cb + *get_connection_property_changed_cb( + struct vpn_connection *connection, + enum vpn_connection_property_type type) +{ + return g_hash_table_lookup(connection->property_changed_cb_hash, + GINT_TO_POINTER(type)); +} + +static void parse_connection_property_ipv4( + struct vpn_connection *connection, + GVariant *ipv4) +{ + DBG(""); + + GVariantIter *iter; + gchar *key; + GVariant *value; + + g_variant_get(ipv4, "a{sv}", &iter); + if (g_variant_iter_n_children(iter) == 0) { + g_variant_iter_free(iter); + return; + } + + if (connection->ipv4) + free_vpn_connection_ipv4(connection->ipv4); + + connection->ipv4 = g_try_new0(struct vpn_connection_ipv4, 1); + if (connection->ipv4 == NULL) { + ERROR("no memory"); + g_variant_iter_free(iter); + return; + } + + while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { + if (!g_strcmp0(key, "Address")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Address is %s", property_value); + connection->ipv4->address = g_strdup(property_value); + } else if (!g_strcmp0(key, "Netmask")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Netmask is %s", property_value); + connection->ipv4->netmask = g_strdup(property_value); + } else if (!g_strcmp0(key, "Gateway")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Gateway is %s", property_value); + connection->ipv4->gateway = g_strdup(property_value); + } else if (!g_strcmp0(key, "Peer")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Peer is %s", property_value); + connection->ipv4->peer = g_strdup(property_value); + } + } + + g_variant_iter_free(iter); +} + +static void parse_connection_property_ipv6( + struct vpn_connection *connection, + GVariant *ipv6) +{ + DBG(""); + + GVariantIter *iter; + gchar *key; + GVariant *value; + + g_variant_get(ipv6, "a{sv}", &iter); + if (g_variant_iter_n_children(iter) == 0) { + g_variant_iter_free(iter); + return; + } + + if (connection->ipv6) + free_vpn_connection_ipv6(connection->ipv6); + + connection->ipv6 = g_try_new0(struct vpn_connection_ipv6, 1); + if (connection->ipv6 == NULL) { + ERROR("no memory"); + g_variant_iter_free(iter); + return; + } + + while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { + if (!g_strcmp0(key, "Address")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Address is %s", property_value); + connection->ipv6->address = g_strdup(property_value); + } else if (!g_strcmp0(key, "PrefixLength")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("PrefixLength is %s", property_value); + connection->ipv6->prefix_length = + g_strdup(property_value); + } else if (!g_strcmp0(key, "Gateway")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Gateway is %s", property_value); + connection->ipv6->gateway = g_strdup(property_value); + } else if (!g_strcmp0(key, "Peer")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Peer is %s", property_value); + connection->ipv6->peer = g_strdup(property_value); + } + } + + g_variant_iter_free(iter); +} + +static void parse_connection_property_nameservers( + struct vpn_connection *connection, + GVariant *nameservers) +{ + DBG(""); + + GVariantIter *iter; + gchar *value; + int i = 0, n; + + g_variant_get(nameservers, "as", &iter); + if (g_variant_iter_n_children(iter) == 0) { + g_variant_iter_free(iter); + return; + } + + g_strfreev(connection->nameservers); + n = g_variant_iter_n_children(iter); + connection->nameservers = g_try_new0(char *, n+1); + if (connection->nameservers == NULL) { + ERROR("no memory"); + g_variant_iter_free(iter); + return; + } + + while (g_variant_iter_loop(iter, "s", &value) && i < n) { + DBG("Nameserver Entry is %s", value); + connection->nameservers[i] = g_strdup(value); + i++; + } + connection->nameservers[n] = NULL; + + g_variant_iter_free(iter); +} + +static void print_variant(const gchar *s, GVariant *v) +{ + gchar *temp = g_variant_print(v, true); + DBG("%s => %s", s, temp); + g_free(temp); +} + +static void parse_connection_property_user_routes( + struct vpn_connection *connection, + GVariant *user_routes) +{ + DBG(""); + + GVariantIter outer; + GVariantIter *route_entry; + + print_variant("Incoming : ", user_routes); + + g_variant_iter_init(&outer, user_routes); + if (g_variant_iter_n_children(&outer) == 0) + return; + + if (connection->user_routes) + g_slist_free_full(connection->user_routes, + free_vpn_connection_route); + + while (g_variant_iter_loop(&outer, "(a{sv})", &route_entry)) { + gchar *key; + GVariant *value; + + if (g_variant_iter_n_children(route_entry) == 0) + continue; + + struct vpn_connection_route *route = + g_try_new0(struct vpn_connection_route, 1); + if (route == NULL) { + ERROR("no memory"); + return; + } + + while (g_variant_iter_loop(route_entry, "{sv}", &key, &value)) { + if (!g_strcmp0(key, "ProtocolFamily")) { + int property_value = g_variant_get_int32(value); + DBG("ProtocolFamily is %d", property_value); + route->protocol_family = property_value; + } else if (!g_strcmp0(key, "Network")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Network is %s", property_value); + route->network = g_strdup(property_value); + } else if (!g_strcmp0(key, "Netmask")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Netmask is %s", property_value); + route->netmask = g_strdup(property_value); + } else if (!g_strcmp0(key, "Gateway")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Gateway is %s", property_value); + route->gateway = g_strdup(property_value); + } + } + + /*TODO: See if g_slist_prepend works better*/ + connection->user_routes = + g_slist_append(connection->user_routes, route); + + } +} + +static void parse_connection_property_server_routes( + struct vpn_connection *connection, + GVariant *server_routes) +{ + DBG(""); + + GVariantIter outer; + GVariantIter *route_entry; + + g_variant_iter_init(&outer, server_routes); + if (g_variant_iter_n_children(&outer) == 0) { + return; + } + + if (connection->server_routes) + g_slist_free_full(connection->server_routes, + free_vpn_connection_route); + + while (g_variant_iter_loop(&outer, "(a{sv})", &route_entry)) { + gchar *key; + GVariant *value; + + if (g_variant_iter_n_children(route_entry) == 0) + continue; + + struct vpn_connection_route *route = + g_try_new0(struct vpn_connection_route, 1); + if (route == NULL) { + ERROR("no memory"); + return; + } + + while (g_variant_iter_loop(route_entry, "{sv}", &key, &value)) { + if (!g_strcmp0(key, "ProtocolFamily")) { + int property_value = g_variant_get_int32(value); + DBG("ProtocolFamily is %d", property_value); + route->protocol_family = property_value; + } else if (!g_strcmp0(key, "Network")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Network is %s", property_value); + route->network = g_strdup(property_value); + } else if (!g_strcmp0(key, "Netmask")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Netmask is %s", property_value); + route->netmask = g_strdup(property_value); + } else if (!g_strcmp0(key, "Gateway")) { + const char *property_value = + g_variant_get_string(value, NULL); + DBG("Gateway is %s", property_value); + route->gateway = g_strdup(property_value); + } + } + + /*TODO: See if g_slist_prepend works better*/ + connection->server_routes = + g_slist_append(connection->server_routes, route); + } +} + +static enum vpn_connection_property_type parse_connection_property( + struct vpn_connection *connection, + gchar *key, GVariant *value) +{ + assert(connection != NULL); + enum vpn_connection_property_type property_type = VPN_CONN_PROP_NONE; + + if (!g_strcmp0(key, "State")) { + const gchar *property_value; + property_value = g_variant_get_string(value, NULL); + DBG("connection state is %s", property_value); + if (!g_strcmp0(property_value, "idle")) + connection->state = VPN_CONN_STATE_IDLE; + else if (!g_strcmp0(property_value, "failure")) + connection->state = VPN_CONN_STATE_FAILURE; + else if (!g_strcmp0(property_value, "configuration")) + connection->state = VPN_CONN_STATE_CONFIGURATION; + else if (!g_strcmp0(property_value, "ready")) + connection->state = VPN_CONN_STATE_READY; + else if (!g_strcmp0(property_value, "disconnect")) + connection->state = VPN_CONN_STATE_DISCONNECT; + property_type = VPN_CONN_PROP_STATE; + } else if (!g_strcmp0(key, "Type")) { + const gchar *property_value; + property_value = g_variant_get_string(value, NULL); + DBG("connection type is %s", property_value); + g_free(connection->type); + connection->type = g_strdup(property_value); + property_type = VPN_CONN_PROP_TYPE; + } else if (!g_strcmp0(key, "Name")) { + const gchar *property_value; + property_value = g_variant_get_string(value, NULL); + g_free(connection->name); + connection->name = g_strdup(property_value); + property_type = VPN_CONN_PROP_NAME; + } else if (!g_strcmp0(key, "Domain")) { + const gchar *property_value; + property_value = g_variant_get_string(value, NULL); + g_free(connection->domain); + connection->domain = g_strdup(property_value); + property_type = VPN_CONN_PROP_DOMAIN; + } else if (!g_strcmp0(key, "Host")) { + const gchar *property_value; + property_value = g_variant_get_string(value, NULL); + g_free(connection->host); + connection->host = g_strdup(property_value); + property_type = VPN_CONN_PROP_HOST; + } else if (!g_strcmp0(key, "Immutable")) { + connection->immutable = g_variant_get_boolean(value); + property_type = VPN_CONN_PROP_IMMUTABLE; + } else if (!g_strcmp0(key, "Index")) { + connection->index = g_variant_get_int32(value); + property_type = VPN_CONN_PROP_INDEX; + } + /* TODO: + * Add IPv4/IPV6/Nameservers + * UserRoutes/ServerRoutes + * Parsing code */ + + else if (!g_strcmp0(key, "IPv4")) { + parse_connection_property_ipv4(connection, value); + property_type = VPN_CONN_PROP_IPV4; + } else if (!g_strcmp0(key, "IPv6")) { + parse_connection_property_ipv6(connection, value); + property_type = VPN_CONN_PROP_IPV6; + } else if (!g_strcmp0(key, "Nameservers")) { + parse_connection_property_nameservers(connection, value); + property_type = VPN_CONN_PROP_USERROUTES; + } else if (!g_strcmp0(key, "UserRoutes")) { + parse_connection_property_user_routes(connection, value); + property_type = VPN_CONN_PROP_USERROUTES; + } else if (!g_strcmp0(key, "ServerRoutes")) { + parse_connection_property_server_routes(connection, value); + property_type = VPN_CONN_PROP_SERVERROUTES; + } + + return property_type; +} + +static void parse_connection_properties( + struct vpn_connection *connection, + GVariantIter *properties) +{ + gchar *key; + GVariant *value; + + while (g_variant_iter_next(properties, "{sv}", &key, &value)) { + parse_connection_property(connection, key, value); + + g_free(key); + g_variant_unref(value); + } +} + +static void connection_property_changed( + struct vpn_connection *connection, + GVariant *parameters) +{ + gchar *key; + GVariant *value; + enum vpn_connection_property_type property_type; + + DBG(""); + + g_variant_get(parameters, "(sv)", &key, &value); + property_type = parse_connection_property(connection, key, value); + + if (property_type != VPN_CONN_PROP_NONE) { + DBG("Now check property changed callback"); + + struct connection_property_changed_cb *property_changed_cb_t; + + property_changed_cb_t = get_connection_property_changed_cb( + connection, + property_type); + if (property_changed_cb_t != NULL) { + DBG("property changed callback has been set"); + property_changed_cb_t->property_changed_cb(connection, + property_changed_cb_t->user_data); + } + } + + g_free(key); + g_variant_unref(value); +} + +static void connection_signal_handler(GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + DBG("signal_name: %s", signal_name); + + struct vpn_connection *connection = user_data; + + if (!g_strcmp0(signal_name, "PropertyChanged")) + connection_property_changed(connection, parameters); +} + +static void free_connection_property_changed_cb(gpointer data) +{ + DBG(""); + struct connection_property_changed_cb *property_changed_cb = data; + + g_free(property_changed_cb); +} + +void destroy_vpn_connections(void) +{ + if (vpn_connection_list != NULL) { + g_list_free(vpn_connection_list); + vpn_connection_list = NULL; + } + if (vpn_connection_hash != NULL) { + g_hash_table_destroy(vpn_connection_hash); + vpn_connection_hash = NULL; + } +} + +static struct vpn_connection *create_vpn_connection( + gchar *object_path, + GVariantIter *properties) +{ + GDBusProxy *connection_proxy; + struct vpn_connection *connection; + GError *error = NULL; + + DBG(""); + + connection_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, NULL, + VPN_NAME, object_path, + VPN_CONNECTION_INTERFACE, NULL, &error); + if (connection_proxy == NULL) { + ERROR("error info: %s", error->message); + g_error_free(error); + return NULL; + } + + connection = g_try_new0(struct vpn_connection, 1); + if (connection == NULL) { + ERROR("no memory"); + g_object_unref(connection_proxy); + return NULL; + } + + connection->dbus_proxy = connection_proxy; + connection->path = g_strdup(object_path); + + parse_connection_properties(connection, properties); + + g_hash_table_insert(vpn_connection_hash, + (gpointer)connection->path, + (gpointer)connection); + + vpn_connection_list = g_list_append(vpn_connection_list, + connection); + + connection->property_changed_cb_hash = g_hash_table_new_full( + g_direct_hash, g_direct_equal, NULL, + free_connection_property_changed_cb); + + g_signal_connect(connection->dbus_proxy, "g-signal", + G_CALLBACK(connection_signal_handler), connection); + + return connection; +} + +static void free_vpn_connection_ipv4(struct vpn_connection_ipv4 *ipv4_info) +{ + DBG(""); + + g_free(ipv4_info->address); + g_free(ipv4_info->netmask); + g_free(ipv4_info->gateway); + g_free(ipv4_info->peer); + g_free(ipv4_info); +} + +static void free_vpn_connection_ipv6(struct vpn_connection_ipv6 *ipv6_info) +{ + DBG(""); + + g_free(ipv6_info->address); + g_free(ipv6_info->prefix_length); + g_free(ipv6_info->gateway); + g_free(ipv6_info->peer); + g_free(ipv6_info); +} + +static void free_vpn_connection_route(gpointer data) +{ + DBG(""); + + struct vpn_connection_route *route = data; + + if (route == NULL) { + DBG("Nothing to Delete!"); + return; + } + + g_free(route->network); + g_free(route->netmask); + g_free(route->gateway); + + g_free(route); +} + +static void free_vpn_connection(gpointer data) +{ + DBG(""); + + struct vpn_connection *connection = data; + + if (connection == NULL) + return; + + if (connection->dbus_proxy != NULL) + g_object_unref(connection->dbus_proxy); + + if (connection->property_changed_cb_hash != NULL) + g_hash_table_destroy(connection->property_changed_cb_hash); + + g_free(connection->path); + g_free(connection->name); + g_free(connection->domain); + g_free(connection->host); + + if (connection->ipv4) + free_vpn_connection_ipv4(connection->ipv4); + + if (connection->ipv6) + free_vpn_connection_ipv6(connection->ipv6); + + g_strfreev(connection->nameservers); + + if (connection->user_routes) + g_slist_free_full(connection->user_routes, + free_vpn_connection_route); + + if (connection->server_routes) + g_slist_free_full(connection->server_routes, + free_vpn_connection_route); + + g_free(connection); +} + +static void create_vpn_connections(GVariant *connections) +{ + GVariantIter *iter; + gchar *path; + GVariantIter *properties; + + g_variant_get(connections, "(a(oa{sv}))", &iter); + if (g_variant_iter_n_children(iter) == 0) { + g_variant_iter_free(iter); + return; + } + + while (g_variant_iter_loop(iter, "(oa{sv})", &path, &properties)) + create_vpn_connection(path, properties); + + g_variant_iter_free(iter); +} + +struct vpn_connection *get_connection_by_path(const gchar *path) +{ + DBG("path: %s", path); + + return g_hash_table_lookup(vpn_connection_hash, (gpointer)path); +} + +gboolean add_vpn_connection(GVariant **parameters, + struct vpn_connection **connection) +{ + gchar *print_str; + gchar *connection_path; + GVariantIter *properties; + gboolean ret; + + g_variant_get(*parameters, "(oa{sv})", &connection_path, &properties); + + print_str = g_variant_print(*parameters, TRUE); + DBG("connection path: %s, parameters: %s", connection_path, print_str); + g_free(print_str); + + /* + * Lookup if it has existed in the hash table + */ + *connection = g_hash_table_lookup(vpn_connection_hash, + (gpointer) connection_path); + if (*connection != NULL) { + DBG("Repetitive connection %s", (*connection)->name); + + ret = FALSE; + } else { + *connection = create_vpn_connection(connection_path, + properties); + if (*connection != NULL) + ret = TRUE; + else + ret = FALSE; + } + + g_variant_iter_free(properties); + return ret; +} + +void remove_vpn_connection(struct vpn_connection *connection) +{ + DBG(""); + + assert(connection != NULL); + + vpn_connection_list = g_list_remove(vpn_connection_list, + (gpointer)connection); + + g_hash_table_remove(vpn_connection_hash, + (gconstpointer)connection->path); +} + +void sync_vpn_connections(void) +{ + DBG(""); + + gchar *print_str; + GVariant *connections; + GError *error = NULL; + + connections = g_dbus_proxy_call_sync(get_vpn_manager_dbus_proxy(), + "GetConnections", NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + if (connections == NULL) { + ERROR("error info: %s", error->message); + g_error_free(error); + return; + } + + print_str = g_variant_print(connections, TRUE); + DBG("connections: %s", print_str); + g_free(print_str); + + if (!vpn_connection_hash) + vpn_connection_hash = g_hash_table_new_full( + g_str_hash, g_str_equal, + NULL, free_vpn_connection); + DBG("hash: %p", vpn_connection_hash); + + create_vpn_connections(connections); + + g_variant_unref(connections); +} + +/** + * VPN Connection Methods + */ +GList *vpn_get_connections(void) +{ + DBG(""); + + return vpn_connection_list; +} + +struct vpn_connection *vpn_get_connection( + const char *host, const char *domain) +{ + if (!host || !domain) + return NULL; + + GList *iter; + + for (iter = vpn_connection_list; iter != NULL; + iter = iter->next) { + struct vpn_connection *connection = + (struct vpn_connection *)(iter->data); + + if (g_str_equal(connection->host, host) && + g_str_equal(connection->domain, domain)) + return connection; + } + + return NULL; +} + +enum dvpnlib_err vpn_connection_clear_property( + struct vpn_connection *connection) +{ + GVariant *value; + + assert(connection != NULL); + + /** + * Only supported the "UserRoutes" item now; + */ + value = g_variant_new("(s)", "UserRoutes"); + + return common_set_interface_call_method_sync(connection->dbus_proxy, + "ClearProperty", &value); +} + +/** + * Asynchronous connect callback + */ +static void connect_callback(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + enum dvpnlib_err error_type = DVPNLIB_ERR_NONE; + GVariant *ret; + struct common_reply_data *reply_data; + struct vpn_connection *connection; + + reply_data = user_data; + if (!reply_data) + return; + + connection = reply_data->user; + if (!connection) + goto done; + + if (!connection->dbus_proxy) + goto done; + + ret = g_dbus_proxy_call_finish(connection->dbus_proxy, res, &error); + if (!ret) { + DBG("%s", error->message); + error_type = get_error_type(error); + + g_error_free(error); + } else + g_variant_unref(ret); + + if (reply_data->cb) { + dvpnlib_reply_cb callback = reply_data->cb; + callback(error_type, reply_data->data); + } + +done: + g_free(reply_data); +} + +enum dvpnlib_err vpn_connection_connect(struct vpn_connection *connection, + dvpnlib_reply_cb callback, + void *user_data) +{ + DBG(""); + + struct common_reply_data *reply_data; + + assert(connection != NULL); + + reply_data = + common_reply_data_new(callback, user_data, connection, TRUE); + + return common_set_interface_call_method(connection->dbus_proxy, + "Connect", NULL, + (GAsyncReadyCallback) + connect_callback, reply_data); +} + +enum dvpnlib_err +vpn_connection_disconnect(struct vpn_connection *connection) +{ + DBG(""); + + assert(connection != NULL); + + return common_set_interface_call_method_sync(connection->dbus_proxy, + "Disconnect", NULL); + +} + +const char *vpn_connection_get_type( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->type; +} + +const char *vpn_connection_get_name( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->name; +} + +const char *vpn_connection_get_path( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->path; +} + +const char *vpn_connection_get_domain( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->domain; +} + +const char *vpn_connection_get_host( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->host; +} + +bool vpn_connection_get_immutable( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->immutable; +} + +int vpn_connection_get_index( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->index; +} + +enum vpn_connection_state vpn_connection_get_state( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->state; +} + +const struct vpn_connection_ipv4 *vpn_connection_get_ipv4( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->ipv4; +} + +const struct vpn_connection_ipv6 *vpn_connection_get_ipv6( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->ipv6; +} + +char **vpn_connection_get_nameservers( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->nameservers; +} + +GSList *vpn_connection_get_user_routes( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->user_routes; +} + +GSList *vpn_connection_get_server_routes( + struct vpn_connection *connection) +{ + assert(connection != NULL); + + return connection->server_routes; +} + +enum dvpnlib_err vpn_connection_set_property_changed_cb( + struct vpn_connection *connection, + enum vpn_connection_property_type type, + vpn_connection_property_changed_cb cb, + void *user_data) +{ + DBG(""); + + if (connection == NULL) + return DVPNLIB_ERR_INVALID_PARAMETER; + + struct connection_property_changed_cb *property_changed_cb_t = + g_try_new0(struct connection_property_changed_cb, 1); + if (property_changed_cb_t == NULL) { + ERROR("no memory"); + return DVPNLIB_ERR_FAILED; + } + property_changed_cb_t->property_changed_cb = cb; + property_changed_cb_t->user_data = user_data; + + g_hash_table_insert(connection->property_changed_cb_hash, + GINT_TO_POINTER(type), + (gpointer)property_changed_cb_t); + + return DVPNLIB_ERR_NONE; +} + +enum dvpnlib_err vpn_connection_unset_property_changed_cb( + struct vpn_connection *connection, + enum vpn_connection_property_type type) +{ + DBG(""); + + if (connection == NULL) + return DVPNLIB_ERR_INVALID_PARAMETER; + + struct connection_property_changed_cb *property_changed_cb_t = + get_connection_property_changed_cb(connection, type); + + if (property_changed_cb_t == NULL) { + DBG("Can't find connection property changed callback"); + return DVPNLIB_ERR_FAILED; + } + + g_hash_table_remove(connection->property_changed_cb_hash, + GINT_TO_POINTER(type)); + + return DVPNLIB_ERR_NONE; +} diff --git a/dvpnlib/src/dvpnlib-vpn-manager.c b/dvpnlib/src/dvpnlib-vpn-manager.c new file mode 100644 index 0000000..dd5fb13 --- /dev/null +++ b/dvpnlib/src/dvpnlib-vpn-manager.c @@ -0,0 +1,321 @@ +#include "dvpnlib-internal.h" +#include "dvpnlib-vpn-manager.h" + +struct vpn_manager { + GDBusProxy *dbus_proxy; + void *connection_added_cb_data; + void *connection_removed_cb_data; + vpn_connection_added_cb connection_added_cb; + vpn_connection_removed_cb connection_removed_cb; +}; + +static void connection_added(GVariant *parameters) +{ + struct vpn_connection *connection; + + DBG(""); + + if (add_vpn_connection(¶meters, &connection)) { + if (vpn_manager->connection_added_cb) { + vpn_manager->connection_added_cb(connection, + vpn_manager->connection_added_cb_data); + } + } +} + +static void connection_removed(GVariant *parameters) +{ + DBG(""); + + const gchar *connection_path; + struct vpn_connection *connection; + + g_variant_get(parameters, "(o)", &connection_path); + + connection = get_connection_by_path(connection_path); + if (connection == NULL) + return; + + if (vpn_manager->connection_removed_cb) { + void *user_data = vpn_manager->connection_removed_cb_data; + vpn_manager->connection_removed_cb(connection, user_data); + } + + remove_vpn_connection(connection); +} + +static void manager_signal_handler(GDBusProxy *proxy, gchar *sender_name, + gchar *signal_name, GVariant *parameters, + gpointer user_data) +{ + DBG("signal_name: %s", signal_name); + + if (!g_strcmp0(signal_name, "ConnectionAdded")) + connection_added(parameters); + else if (!g_strcmp0(signal_name, "ConnectionRemoved")) + connection_removed(parameters); +} + +void free_vpn_manager(struct vpn_manager *manager) +{ + DBG(""); + + if (manager == NULL) + return; + + if (manager->dbus_proxy != NULL) + g_object_unref(manager->dbus_proxy); + + g_free(manager); +} + +struct vpn_manager *create_vpn_manager(void) +{ + GError *error = NULL; + struct vpn_manager *manager; + + DBG(""); + manager = g_try_new0(struct vpn_manager, 1); + if (manager == NULL) { + ERROR("no memory"); + return NULL; + } + + manager->dbus_proxy = g_dbus_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, NULL, + VPN_NAME, VPN_MANAGER_PATH, + VPN_MANAGER_INTERFACE, NULL, &error); + + if (manager->dbus_proxy == NULL) { + ERROR("error info: %s", error->message); + g_error_free(error); + free_vpn_manager(manager); + return NULL; + } + + g_signal_connect(manager->dbus_proxy, "g-signal", + G_CALLBACK(manager_signal_handler), NULL); + + return manager; +} + +GDBusProxy *get_vpn_manager_dbus_proxy(void) +{ + return vpn_manager->dbus_proxy; +} + +/** + * Asynchronous Methods Create/Remove callback + */ +static void create_remove_callback(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + enum dvpnlib_err error_type = DVPNLIB_ERR_NONE; + GVariant *ret; + struct common_reply_data *reply_data; + + reply_data = user_data; + if (!reply_data) + return; + + if (!vpn_manager) + goto done; + + if (!vpn_manager->dbus_proxy) + goto done; + + ret = g_dbus_proxy_call_finish(vpn_manager->dbus_proxy, res, &error); + if (!ret) { + DBG("%s", error->message); + error_type = get_error_type(error); + + g_error_free(error); + } else + g_variant_unref(ret); + + if (reply_data->cb) { + dvpnlib_reply_cb callback = reply_data->cb; + callback(error_type, reply_data->data); + } + +done: + g_free(reply_data); +} + +/* Implementation vpn-manager.h */ + +static void print_variant(const gchar *s, GVariant *v) +{ + gchar *temp = g_variant_print(v, true); + DBG("%s => %s", s, temp); + g_free(temp); +} + +static GVariant * +settings_from_hash_table(GHashTable *hash_table) +{ + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a{sv})")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}")); + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, hash_table); + while (g_hash_table_iter_next(&iter, &key, &value)) { + g_variant_builder_add(&builder, "{sv}", + key, + g_variant_new_string(value)); + } + + g_variant_builder_close(&builder); + + return g_variant_builder_end(&builder); +} + +enum dvpnlib_err dvpnlib_vpn_manager_create(GHashTable *settings, + dvpnlib_reply_cb callback, + void *user_data) +{ + GVariant *settings_v; + + assert(vpn_manager != NULL); + assert(settings != NULL); + + settings_v = settings_from_hash_table(settings); + print_variant("Settings", settings_v); + + struct common_reply_data *reply_data; + + reply_data = + common_reply_data_new(callback, user_data, NULL, TRUE); + + if (NULL == reply_data) { + DBG("No Memory Available!"); + return DVPNLIB_ERR_FAILED; + } + + return common_set_interface_call_method( + vpn_manager->dbus_proxy, + "Create", + &settings_v, + (GAsyncReadyCallback)create_remove_callback, + reply_data); +} + +enum dvpnlib_err dvpnlib_vpn_manager_remove(const char *path, + dvpnlib_reply_cb callback, + void *user_data) +{ + GVariant *value; + enum dvpnlib_err ret = DVPNLIB_ERR_NONE; + + assert(vpn_manager != NULL); + + if (!g_variant_is_object_path(path)) + return DVPNLIB_ERR_FAILED; + + value = g_variant_new("(o)", path); + + struct common_reply_data *reply_data; + + reply_data = + common_reply_data_new(callback, user_data, NULL, TRUE); + + if (NULL == reply_data) { + DBG("No Memory Available!"); + return DVPNLIB_ERR_FAILED; + + } + + ret = common_set_interface_call_method( + vpn_manager->dbus_proxy, + "Remove", + &value, + (GAsyncReadyCallback)create_remove_callback, + reply_data); + + return ret; +} + +enum dvpnlib_err dvpnlib_vpn_manager_register_agent(const char *path) +{ + GVariant *value; + + assert(vpn_manager != NULL); + + if (!g_variant_is_object_path(path)) + return DVPNLIB_ERR_FAILED; + + value = g_variant_new("(o)", path); + + return common_set_interface_call_method_sync( + vpn_manager->dbus_proxy, + "RegisterAgent", + &value); +} + +enum dvpnlib_err dvpnlib_vpn_manager_unregister_agent(const char *path) +{ + GVariant *value; + + assert(vpn_manager != NULL); + + if (!g_variant_is_object_path(path)) + return DVPNLIB_ERR_FAILED; + + value = g_variant_new("(o)", path); + + return common_set_interface_call_method_sync( + vpn_manager->dbus_proxy, + "UnregisterAgent", + &value); +} + +void dvpnlib_vpn_manager_set_connection_added_cb( + vpn_connection_added_cb cb, + void *user_data) +{ + DBG(""); + + assert(vpn_manager != NULL); + + vpn_manager->connection_added_cb = cb; + vpn_manager->connection_added_cb_data = user_data; +} + +void dvpnlib_vpn_manager_unset_connection_added_cb() +{ + DBG(""); + + assert(vpn_manager != NULL); + + vpn_manager->connection_added_cb = NULL; + vpn_manager->connection_added_cb_data = NULL; +} + +void dvpnlib_vpn_manager_set_connection_removed_cb( + vpn_connection_removed_cb cb, + void *user_data) +{ + DBG(""); + + assert(vpn_manager != NULL); + + vpn_manager->connection_removed_cb = cb; + vpn_manager->connection_removed_cb_data = user_data; +} + +void dvpnlib_vpn_manager_unset_connection_removed_cb() +{ + DBG(""); + + assert(vpn_manager != NULL); + + vpn_manager->connection_removed_cb = NULL; + vpn_manager->connection_removed_cb_data = NULL; +} + diff --git a/dvpnlib/src/dvpnlib-vpn.c b/dvpnlib/src/dvpnlib-vpn.c new file mode 100644 index 0000000..5a0e962 --- /dev/null +++ b/dvpnlib/src/dvpnlib-vpn.c @@ -0,0 +1,33 @@ +#include "dvpnlib-internal.h" +#include "dvpnlib-vpn.h" + +struct vpn_manager *vpn_manager; + +int dvpnlib_vpn_init(void) +{ + DBG(""); + + if (vpn_manager != NULL) + return 0; + + vpn_manager = create_vpn_manager(); + + if (vpn_manager == NULL) { + DBG("can't create vpn manager"); + return -1; + } + + sync_vpn_connections(); + + return 0; +} + +void dvpnlib_vpn_deinit(void) +{ + DBG(""); + + free_vpn_manager(vpn_manager); + vpn_manager = NULL; + + destroy_vpn_connections(); +} diff --git a/dvpnlib/src/dvpnlib.c b/dvpnlib/src/dvpnlib.c new file mode 100644 index 0000000..b603946 --- /dev/null +++ b/dvpnlib/src/dvpnlib.c @@ -0,0 +1,180 @@ +#include "dvpnlib-internal.h" + +/* + * D-Bus + */ +enum dvpnlib_err common_set_property(GDBusProxy *dbus_proxy, + const char *property, + GVariant *value) +{ + gchar *print_str; + GError *error = NULL; + enum dvpnlib_err ret = DVPNLIB_ERR_NONE; + + print_str = g_variant_print(value, TRUE); + DBG("set object %s property %s to %s", + g_dbus_proxy_get_object_path(dbus_proxy), + property, print_str); + g_free(print_str); + + g_dbus_proxy_call_sync(dbus_proxy, "SetProperty", + g_variant_new("(sv)", property, value), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERROR("%s", error->message); + ret = get_error_type(error); + g_error_free(error); + } + + return ret; +} + +GVariant *common_get_call_method_result(GDBusProxy *dbus_proxy, + const char *method) +{ + if ((!dbus_proxy) || (!method)) + return NULL; + + GError *error = NULL; + GVariant *result; + + DBG("get object %s method %s", + g_dbus_proxy_get_object_path(dbus_proxy), method); + + result = g_dbus_proxy_call_sync(dbus_proxy, method, NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + if (!result) { + ERROR("%s", error->message); + g_error_free(error); + return NULL; + } + + return result; +} + +enum dvpnlib_err common_set_interface_call_method_sync( + GDBusProxy *dbus_proxy, + const char *method, + GVariant **parameters) +{ + if ((!dbus_proxy) || (!method)) + return DVPNLIB_ERR_FAILED; + + GVariant *result; + GError *error = NULL; + enum dvpnlib_err ret = DVPNLIB_ERR_NONE; + + DBG("get object %s property %s", + g_dbus_proxy_get_object_path(dbus_proxy), method); + + if (parameters) + result = g_dbus_proxy_call_sync(dbus_proxy, method, *parameters, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + else + result = g_dbus_proxy_call_sync(dbus_proxy, method, NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + ERROR("%s", error->message); + ret = get_error_type(error); + g_error_free(error); + return ret; + } + + g_variant_unref(result); + + return ret; +} + +enum dvpnlib_err common_set_interface_call_method(GDBusProxy *dbus_proxy, + const char *method, + GVariant **parameters, + GAsyncReadyCallback callback, + gpointer user_data) +{ + if ((!dbus_proxy) || (!method)) + return DVPNLIB_ERR_FAILED; + + DBG("get object %s property %s", + g_dbus_proxy_get_object_path(dbus_proxy), method); + + if (parameters) { + g_dbus_proxy_call(dbus_proxy, + method, + *parameters, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, callback, user_data); + } else { + g_dbus_proxy_call(dbus_proxy, + method, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, callback, user_data); + } + + return DVPNLIB_ERR_NONE; +} + +struct common_reply_data *common_reply_data_new(void *cb, void *data, + void *user, bool flag) +{ + struct common_reply_data *ret; + + ret = g_try_new0(struct common_reply_data, 1); + if (!ret) + return NULL; + + ret->cb = cb; + ret->data = data; + ret->user = user; + ret->flag = flag; + + return ret; +} + +/* + * Error + */ +struct error_map_t error_map[] = { + {"Error.Failed", DVPNLIB_ERR_OPERATION_FAILED}, + {"Error.InvalidArguments", DVPNLIB_ERR_INVALID_PARAMETER}, + {"Error.PermissionDenied", DVPNLIB_ERR_PERMISSION_DENIED}, + {"Error.PassphraseRequired", DVPNLIB_ERR_PASSPHRASE_REQUIRED}, + {"Error.NotRegistered", DVPNLIB_ERR_NOT_REGISTERED}, + {"Error.NotUnique", DVPNLIB_ERR_NOT_UNIQUE}, + {"Error.NotSupported", DVPNLIB_ERR_NOT_SUPPORTED}, + {"Error.NotImplemented", DVPNLIB_ERR_NOT_IMPLEMENTED}, + {"Error.NotFound", DVPNLIB_ERR_NOT_FOUND}, + {"Error.InProgress", DVPNLIB_ERR_IN_PROGRESS}, + {"Error.AlreadyExists", DVPNLIB_ERR_ALREADY_EXISTS}, + {"Error.AlreadyEnabled", DVPNLIB_ERR_ALREADY_ENABLED}, + {"Error.AlreadyDisabled", DVPNLIB_ERR_ALREADY_DISABLED}, + {"Error.AlreadyConnected", DVPNLIB_ERR_ALREADY_CONNECTED}, + {"Error.NotConnected", DVPNLIB_ERR_NOT_CONNECTED}, + {"Error.OperationAborted", DVPNLIB_ERR_OPERATION_ABORTED}, + {"Error.OperationTimeout", DVPNLIB_ERR_OPERATION_TIMEOUT}, + {"Error.InvalidService", DVPNLIB_ERR_INVALID_SERVICE}, + {"Error.InvalidProperty", DVPNLIB_ERR_INVALID_PROPERTY}, + + {"Error.Timeout", DVPNLIB_ERR_TIMEOUT}, + {"Error.Timedout", DVPNLIB_ERR_TIMEOUT}, + {"Error.UnknownProperty", DVPNLIB_ERR_UNKNOWN_PROPERTY}, + {"Error.PropertyReadOnly", DVPNLIB_ERR_PROPERTY_READONLY}, + {"Error.UnknownMethod", DVPNLIB_ERR_UNKNOWN_METHOD}, +}; + +enum dvpnlib_err get_error_type(GError *error) +{ + int i = 0; + + while (error_map[i].error_key_str != NULL) { + const gchar *error_info = error_map[i].error_key_str; + + if (g_strrstr(error->message, error_info)) + return error_map[i].type; + + i++; + } + + return DVPNLIB_ERR_FAILED; +} diff --git a/include/vpn.h b/include/vpn.h new file mode 100644 index 0000000..ab6e7ea --- /dev/null +++ b/include/vpn.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_NETWORK_VPN_H__ +#define __TIZEN_NETWORK_VPN_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @addtogroup CAPI_NETWORK_VPN_MANAGER_MODULE +* @{ +*/ + +/** + * @brief The handle for vpn. + */ +typedef void *vpn_h; +typedef void *vpn_settings_h; + +/** +* @brief The VPN error type +*/ +typedef enum { + VPN_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + VPN_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + VPN_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory error */ + VPN_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */ + VPN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED = TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED, /**< Address family not supported */ + VPN_ERROR_OPERATION_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0301, /**< Operation failed */ + VPN_ERROR_NO_CONNECTION = TIZEN_ERROR_NETWORK_CLASS|0x0302, /**< There is no connected AP */ + VPN_ERROR_NOW_IN_PROGRESS = TIZEN_ERROR_NOW_IN_PROGRESS, /** Now in progress */ + VPN_ERROR_ALREADY_EXISTS = TIZEN_ERROR_NETWORK_CLASS|0x0303, /**< Already exists */ + VPN_ERROR_OPERATION_ABORTED = TIZEN_ERROR_NETWORK_CLASS|0x0304, /**< Operation is aborted */ + VPN_ERROR_DHCP_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0306, /**< DHCP failed */ + VPN_ERROR_INVALID_KEY = TIZEN_ERROR_NETWORK_CLASS|0x0307, /**< Invalid key */ + VPN_ERROR_NO_REPLY = TIZEN_ERROR_NETWORK_CLASS|0x0308, /**< No reply */ + VPN_ERROR_SECURITY_RESTRICTED = TIZEN_ERROR_NETWORK_CLASS|0x0309, /**< Restricted by security system policy */ +} vpn_error_e; + +/** +* @} +*/ + +/** +* @addtogroup CAPI_NETWORK_VPN_MONITOR_MODULE +* @{ +*/ + +/** +* @brief Called after vpn_create() is completed. +* @param[in] result The result +* @param[in] user_data The user data passed from vpn_create() +* @pre vpn_create() will invoke this callback function. +* @see vpn_create() +*/ +typedef void(*vpn_created_cb)(vpn_error_e result, void *user_data); + +/** +* @brief Called after vpn_remove() is completed. +* @param[in] result The result +* @param[in] user_data The user data passed from vpn_remove() +* @pre vpn_remove() will invoke this callback function. +* @see vpn_remove() +*/ +typedef void(*vpn_removed_cb)(vpn_error_e result, void *user_data); +/** +* @} +*/ + +/** +* @brief Called after vpn_connect() is completed. +* @param[in] result The result +* @param[in] user_data The user data passed from vpn_connect() +* @pre vpn_connect() will invoke this callback function. +* @see vpn_connect() +*/ +typedef void(*vpn_connect_cb)(vpn_error_e result, void *user_data); + +/** +* @brief Called after vpn_disconnect() is completed. +* @param[in] result The result +* @param[in] user_data The user data passed from vpn_disconnect() +* @pre vpn_disconnect() will invoke this callback function. +* @see vpn_disconnect() +*/ +typedef void(*vpn_disconnect_cb)(vpn_error_e result, void *user_data); +/** +* @} +*/ + + +/** +* @addtogroup CAPI_NETWORK_VPN_MODULE +* @{ +*/ + +/** +* @brief Initializes VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +*/ +int vpn_initialize(void); + +/** +* @brief Deinitializes VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +*/ +int vpn_deinitialize(void); + +/** +* @} +*/ + +/** +* @addtogroup CAPI_NETWORK_VPN_SETTINGS +* @{ +*/ + +/** +* @brief Initializes VPN Settings +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() +*/ +int vpn_settings_init(); + +/** +* @brief De-Initializes VPN Settings +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @pre vpn_settings_init() Must be called before deinit +* @see vpn_settings_deinit() +*/ +int vpn_settings_deinit(); + +/** +* @brief Sets VPN Specific Settings +* @param[in] key The Key for the Settings +* @param[in] value The Value for the Settings +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @pre vpn_settings_init() must be called before calling this API +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() +*/ +int vpn_settings_set_specific(const char *key, const char *value); + +/** +* @brief Sets VPN Type +* @param[in] type The VPN Settings Type +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @pre vpn_settings_init() must be called before calling this API +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() vpn_settings_init() +*/ +int vpn_settings_set_type(const char *type); + +/** +* @brief Sets VPN Profile Name +* @param[in] name The VPN Settings Name +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @pre vpn_settings_init() must be called before calling this API +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() vpn_settings_init() +*/ +int vpn_settings_set_name(const char *name); + +/** +* @brief Sets VPN Profile Host (Name or Address) +* @param[in] host The VPN Settings Host +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @pre vpn_settings_init() must be called before calling this API +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() vpn_settings_init() +*/ +int vpn_settings_set_host(const char *host); + +/** +* @brief Sets VPN Profile Domain +* @param[in] domain The VPN Settings Domain +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @pre vpn_settings_init() must be called before calling this API +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @see vpn_settings_deinit() vpn_settings_init() +*/ +int vpn_settings_set_domain(const char *domain); + +/** +* @} +*/ + + +/** +* @addtogroup CAPI_NETWORK_VPN_MANAGER_MODULE +* @{ +*/ + +/** +* @brief Create VPN Profile, asynchronously. +* @param[in] settings The VPN related Settings Handler, This can't be NULL. +* @param[in] callback The callback function to be called. +* This can be NULL if you don't want to get the notification. +* @param[in] user_data The user data passed to the callback function +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @retval #VPN_ERROR_SECURITY_RESTRICTED Restricted by security system policy +* @post vpn_created_cb() will be invoked +* @see vpn_settings() +* @see vpn_created_cb() +* @see vpn_remove() +*/ +int vpn_create(vpn_created_cb callback, void *user_data); + +/** +* @brief Remove VPN Profile, asynchronously. +* @param[in] handle The VPN Connection Identifier. +* @param[in] callback The callback function to be called. +* This can be NULL if you don't want to get the notification. +* @param[in] user_data The user data passed to the callback function +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @post vpn_removed_cb() will be invoked +* @see vpn_removed_cb() +* @see vpn_create() +*/ +int vpn_remove(vpn_h handle, vpn_removed_cb callback, void *user_data); + +/** +* @} +*/ + + +/** +* @addtogroup CAPI_NETWORK_VPN_CONNECTION_MODULE +* @{ +*/ + +/** +* @brief Connect to a VPN Profile, asynchronously. +* @param[in] settings The VPN related Settings Handler, This can't be NULL. +* @param[in] callback The callback function to be called. +* This can be NULL if you don't want to get the notification. +* @param[in] user_data The user data passed to the callback function +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @retval #VPN_ERROR_ALREADY_EXISTS Restricted by security system policy +* @see vpn_connect_cb() +* @see vpn_disconnect() +*/ +int vpn_connect(vpn_h handle, vpn_connect_cb callback, void *user_data); + +/** +* @brief Disconnect from VPN Profile, asynchronously. +* @param[in] handle The VPN Connection Identifier. +* @param[in] callback The callback function to be called. +* This can be NULL if you don't want to get the notification. +* @param[in] user_data The user data passed to the callback function +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_OPERATION_FAILED Operation failed +* @retval #VPN_ERROR_NO_CONNECTION No Connection +* @see vpn_disconnect_cb() +* @see vpn_connect() +*/ +int vpn_disconnect(vpn_h handle, vpn_disconnect_cb callback, void *user_data); + +/** +* @brief Gets the VPN Handle List. +* @return Valid GList Pointer on success, otherwise NULL. +* @see vpn_get_vpn_handle() +*/ +GList *vpn_get_vpn_handle_list(void); + +/** +* @brief Get Specific VPN Handle based on host & domain. +* @param[in] host The VPN Host Identifier. +* @param[in] domain The VPN Domain Identifier. +* @param[out] handle The VPN handle that matches host & domain. +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_INVALID_PARAMETER Operation failed +* @see vpn_get_vpn_handle_list() +*/ +int vpn_get_vpn_handle(const char *host, const char *domain, vpn_h *handle); + +/** +* @brief Get VPN Info (Name) +* @param[in] handle The VPN handle for the Request +* @param[out] name Name of the VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_INVALID_PARAMETER Operation failed +*/ +int vpn_get_vpn_info_name(const vpn_h handle, const char **name); + +/** +* @brief Get VPN Info (Type) +* @param[in] handle The VPN handle for the Request +* @param[out] type Type of the VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_INVALID_PARAMETER Operation failed +*/ +int vpn_get_vpn_info_type(const vpn_h handle, const char **type); + +/** +* @brief Get VPN Info (Host) +* @param[in] handle The VPN handle for the Request +* @param[out] host Host of the VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_INVALID_PARAMETER Operation failed +*/ +int vpn_get_vpn_info_host(const vpn_h handle, const char **host); + +/** +* @brief Get VPN Info (Domain) +* @param[in] handle The VPN handle for the Request +* @param[out] domain Domain of the VPN +* @return 0 on success, otherwise negative error value. +* @retval #VPN_ERROR_NONE Successful +* @retval #VPN_ERROR_INVALID_OPERATION Invalid operation +* @retval #VPN_ERROR_INVALID_PARAMETER Operation failed +*/ +int vpn_get_vpn_info_domain(const vpn_h handle, const char **domain); + +/** +* @} +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_NETWORK_VPN_H__ */ diff --git a/packaging/capi-network-vpn.manifest b/packaging/capi-network-vpn.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/capi-network-vpn.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/capi-network-vpn.spec b/packaging/capi-network-vpn.spec new file mode 100644 index 0000000..07075d2 --- /dev/null +++ b/packaging/capi-network-vpn.spec @@ -0,0 +1,70 @@ +Name: capi-network-vpn +Summary: Default VPN Library +Version: 0.1.0_0 +Release: 1 +Group: System/Network +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1001: capi-network-vpn.manifest +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(capi-base-common) + +%description +Library code for CAPI's to interact with the Default VPN functionality on TIZEN platform. + +%package devel +Summary: Default VPN Development Package +Group: System/Network +Requires: %{name} = %{version}-%{release} + +%description devel +Development Library for Default VPN functionality on TIZEN platform. + +%package test +Summary: Default VPN Test Package +Requires: %{name} = %{version} + +%description test +Test cases for Default VPN Functionality on TIZEN platform. + +%prep +%setup -q +cp %{SOURCE1001} . + + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER} + +make %{?_smp_mflags} + + +%install +%make_install + +#License +mkdir -p %{buildroot}%{_datadir}/license +cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/capi-network-vpn + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + + +%files +%manifest %{name}.manifest +%attr(644,-,-) %{_libdir}/libcapi-network-vpn.so.* +%{_datadir}/license/capi-network-vpn + +%files devel +%manifest %{name}.manifest +#%{_includedir}/network/*.h +%{_libdir}/pkgconfig/*.pc +%{_libdir}/libcapi-network-vpn.so + +%files test +%manifest %{name}.manifest +%{_libdir}/vpn-capi-test/capi-vpn-test diff --git a/src/include/common.h b/src/include/common.h new file mode 100644 index 0000000..a0c6053 --- /dev/null +++ b/src/include/common.h @@ -0,0 +1,57 @@ +/* +* Network VPN library +* +* Copyright (c) 2014-2015 Samsung Electronics. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +#ifndef __NETWORK_VPN_COMMON_H__ +#define __NETWORK_VPN_COMMON_H__ + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * \addtogroup profile_managing + * \{ +*/ + +/*=========================================================================== + CONSTANTS +=============================================================================*/ + + +/*=========================================================================== + ENUMS +=============================================================================*/ + + +/*=========================================================================== + STRUCTURES AND OTHER TYPEDEFS +=============================================================================*/ + + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NETWORK_VPN_COMMON_H__ */ diff --git a/src/include/vpn-internal.h b/src/include/vpn-internal.h new file mode 100644 index 0000000..7669aa0 --- /dev/null +++ b/src/include/vpn-internal.h @@ -0,0 +1,83 @@ +/* +* Network VPN library +* +* Copyright (c) 2014-2015 Samsung Electronics. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +#ifndef __VPN_CONNECTION_PRIVATE_H__ +#define __VPN_CONNECTION_PRIVATE_H__ + +#include + +#include "vpn.h" +#include "common.h" + +#define LOGI(fmt, arg...) printf("%s:%d %s() " fmt "\n", \ + __FILE__, __LINE__, __func__, ## arg) +#define LOGW(fmt, arg...) printf("warning %s:%d %s() " fmt "\n", \ + __FILE__, __LINE__, __func__, ## arg) +#define LOGE(fmt, arg...) printf("error %s:%d %s() " fmt "\n", \ + __FILE__, __LINE__, __func__, ## arg) + +#undef LOG_TAG +#define LOG_TAG "CAPI_NETWORK_VPN" + +#define VPN_INFO 1 +#define VPN_ERROR 2 +#define VPN_WARN 3 + +#define VPN_LOG(log_level, format, args...) \ + do { \ + switch (log_level) { \ + case VPN_ERROR: \ + LOGE(format, ## args); \ + break; \ + case VPN_WARN: \ + LOGW(format, ## args); \ + break; \ + default: \ + LOGI(format, ## args); \ + } \ + } while (0) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +bool _vpn_init(void); +bool _vpn_deinit(void); + +int _vpn_settings_init(); +int _vpn_settings_deinit(); +int _vpn_settings_set_specific(const char *key, const char *value); + +int _vpn_create(vpn_created_cb callback, void *user_data); +int _vpn_remove(vpn_h handle, vpn_removed_cb callback, void *user_data); + +int _vpn_connect(vpn_h handle, vpn_removed_cb callback, void *user_data); +int _vpn_disconnect(vpn_h handle); + +GList *_vpn_get_vpn_handle_list(void); +int _vpn_get_vpn_handle(const char *host, const char *domain, vpn_h *handle); +int _vpn_get_vpn_info_name(vpn_h handle, const char **name); +int _vpn_get_vpn_info_type(vpn_h handle, const char **type); +int _vpn_get_vpn_info_host(vpn_h handle, const char **host); +int _vpn_get_vpn_info_domain(vpn_h handle, const char **domain); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/src/vpn-internal.c b/src/vpn-internal.c new file mode 100644 index 0000000..63293ad --- /dev/null +++ b/src/vpn-internal.c @@ -0,0 +1,417 @@ +/* +* Network VPN library +* +* Copyright (c) 2014-2015 Samsung Electronics. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "vpn-internal.h" + +struct _vpn_cb_s { + vpn_created_cb create_cb; + void *create_user_data; + vpn_removed_cb remove_cb; + void *remove_user_data; + vpn_connect_cb connect_cb; + void *connect_user_data; + vpn_disconnect_cb disconnect_cb; + void *disconnect_user_data; +}; + +static struct _vpn_cb_s vpn_callbacks = {0,}; +static GHashTable *settings_hash; + +/* + * Utility Functions + */ + +static void print_key_value_string(gpointer key, + gpointer value, gpointer user_data) +{ + if (user_data) { + VPN_LOG(VPN_INFO, " %s[%s]=%s", + (gchar *)user_data, (gchar *)key, (gchar *)value); + return; + } + VPN_LOG(VPN_INFO, " %s=%s", (gchar *)key, (gchar *)value); +} + +vpn_error_e _dvpnlib_error2vpn_error(enum dvpnlib_err err_type) +{ + switch (err_type) { + case DVPNLIB_ERR_NONE: + return VPN_ERROR_NONE; + case DVPNLIB_ERR_ALREADY_EXISTS: + return VPN_ERROR_INVALID_OPERATION; + case DVPNLIB_ERR_NOT_REGISTERED: + return VPN_ERROR_INVALID_OPERATION; + case DVPNLIB_ERR_NOT_CONNECTED: + return VPN_ERROR_NO_CONNECTION; + case DVPNLIB_ERR_ALREADY_CONNECTED: + return VPN_ERROR_ALREADY_EXISTS; + case DVPNLIB_ERR_IN_PROGRESS: + return VPN_ERROR_NOW_IN_PROGRESS; + case DVPNLIB_ERR_OPERATION_ABORTED: + return VPN_ERROR_OPERATION_ABORTED; + case DVPNLIB_ERR_OPERATION_TIMEOUT: + case DVPNLIB_ERR_TIMEOUT: + return VPN_ERROR_NO_REPLY; + default: + return VPN_ERROR_OPERATION_FAILED; + } +} + +/* + *Functions Actually use Default VPN Library + */ + +bool _vpn_init(void) +{ + int rv; + + rv = dvpnlib_vpn_init(); + + if (rv != 0) + return false; + + return true; +} + +bool _vpn_deinit(void) +{ + dvpnlib_vpn_deinit(); + return true; +} + +int _vpn_settings_init() +{ + if (settings_hash != NULL) { + VPN_LOG(VPN_INFO, + "Settings Hash: %p Already present!", settings_hash); + return VPN_ERROR_INVALID_OPERATION; + } + + settings_hash = g_hash_table_new_full( + g_str_hash, g_str_equal, + g_free, g_free); + VPN_LOG(VPN_INFO, "Settings Hash: %p", settings_hash); + + return VPN_ERROR_NONE; +} + +int _vpn_settings_deinit() +{ + if (settings_hash == NULL) + return VPN_ERROR_INVALID_OPERATION; + + VPN_LOG(VPN_INFO, "Settings Hash: %p Destroyed", settings_hash); + g_hash_table_destroy(settings_hash); + settings_hash = NULL; + + return VPN_ERROR_NONE; +} + +int _vpn_settings_set_specific(const char *key, const char *value) +{ + VPN_LOG(VPN_INFO, + "Settings Hash: %p {%s=%s}", settings_hash, key, value); + + if (key == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + if (g_hash_table_contains(settings_hash, key)) { + if (value == NULL) { + VPN_LOG(VPN_INFO, "Settings Hash: %p {%s=%s} (Removed)", + settings_hash, key, + (gchar *)g_hash_table_lookup( + settings_hash, key)); + g_hash_table_remove(settings_hash, key); + return VPN_ERROR_NONE; + } + } + + g_hash_table_replace(settings_hash, + (gpointer)g_strdup(key), + (gpointer)g_strdup(value)); + + return VPN_ERROR_NONE; +} + +/* + *Callbacks + */ +static void __vpn_create_cb(vpn_error_e result) +{ + if (vpn_callbacks.create_cb) + vpn_callbacks.create_cb(result, + vpn_callbacks.create_user_data); + + vpn_callbacks.create_cb = NULL; + vpn_callbacks.create_user_data = NULL; +} + +static void vpn_manager_create_cb(enum dvpnlib_err result, + void *user_data) +{ + VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data); + + __vpn_create_cb(_dvpnlib_error2vpn_error(result)); +} + +static void __vpn_remove_cb(vpn_error_e result) +{ + if (vpn_callbacks.create_cb) + vpn_callbacks.create_cb(result, + vpn_callbacks.create_user_data); + + vpn_callbacks.remove_cb = NULL; + vpn_callbacks.remove_user_data = NULL; +} + +static void vpn_manager_remove_cb(enum dvpnlib_err result, + void *user_data) +{ + VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data); + + __vpn_remove_cb(_dvpnlib_error2vpn_error(result)); +} + +int _vpn_create(vpn_created_cb callback, void *user_data) +{ + enum dvpnlib_err err = DVPNLIB_ERR_NONE; + if (!settings_hash) + return VPN_ERROR_INVALID_OPERATION; + + VPN_LOG(VPN_INFO, ""); + + vpn_callbacks.create_cb = callback; + vpn_callbacks.create_user_data = user_data; + + g_hash_table_foreach(settings_hash, + print_key_value_string, "VPNSettings"); + + err = dvpnlib_vpn_manager_create(settings_hash, + vpn_manager_create_cb, NULL); + if (err != DVPNLIB_ERR_NONE) + return _dvpnlib_error2vpn_error(err); + + return VPN_ERROR_NONE; + +} + +int _vpn_remove(vpn_h handle, vpn_removed_cb callback, void *user_data) +{ + enum dvpnlib_err err = DVPNLIB_ERR_NONE; + + VPN_LOG(VPN_INFO, ""); + + vpn_callbacks.remove_cb = callback; + vpn_callbacks.remove_user_data = user_data; + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + const char *path = vpn_connection_get_path(handle); + err = dvpnlib_vpn_manager_remove(path, vpn_manager_remove_cb, NULL); + if (err != DVPNLIB_ERR_NONE) + return _dvpnlib_error2vpn_error(err); + + return VPN_ERROR_NONE; +} + +/* + *Connect Disconnect Callbacks + */ + +static void __vpn_connect_cb(vpn_error_e result) +{ + if (vpn_callbacks.connect_cb) + vpn_callbacks.connect_cb(result, + vpn_callbacks.connect_user_data); + + vpn_callbacks.connect_cb = NULL; + vpn_callbacks.connect_user_data = NULL; +} + +static void vpn_manager_connect_cb(enum dvpnlib_err result, + void *user_data) +{ + VPN_LOG(VPN_INFO, "callback: %d Settings: %p\n", result, user_data); + + __vpn_connect_cb(_dvpnlib_error2vpn_error(result)); +} + +/* + *Connect to VPN Profile + */ + +int _vpn_connect(vpn_h handle, vpn_removed_cb callback, void *user_data) +{ + enum dvpnlib_err err = DVPNLIB_ERR_NONE; + + VPN_LOG(VPN_INFO, ""); + + vpn_callbacks.connect_cb = callback; + vpn_callbacks.connect_user_data = user_data; + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + enum vpn_connection_state state = vpn_connection_get_state(handle); + if (state == VPN_CONN_STATE_READY) + return VPN_ERROR_ALREADY_EXISTS; + + err = vpn_connection_connect(handle, vpn_manager_connect_cb, NULL); + if (err != DVPNLIB_ERR_NONE) + return _dvpnlib_error2vpn_error(err); + + return VPN_ERROR_NONE; +} + +/* + *Disconnect from VPN Profile + */ + +int _vpn_disconnect(vpn_h handle) +{ + enum dvpnlib_err err = DVPNLIB_ERR_NONE; + + VPN_LOG(VPN_INFO, ""); + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + enum vpn_connection_state state = vpn_connection_get_state(handle); + if (state != VPN_CONN_STATE_READY) + return VPN_ERROR_NO_CONNECTION; + + err = vpn_connection_disconnect(handle); + if (err != DVPNLIB_ERR_NONE) + return _dvpnlib_error2vpn_error(err); + + return VPN_ERROR_NONE; +} + +/* + *Gets the VPN Handles List from VPN Profile + */ +GList *_vpn_get_vpn_handle_list(void) +{ + return vpn_get_connections(); +} + +/* + * Get a specific VPN Handle based on host & domain parameters + */ +int _vpn_get_vpn_handle(const char *host, const char *domain, vpn_h *handle) +{ + VPN_LOG(VPN_INFO, ""); + + struct vpn_connection *connection = vpn_get_connection(host, domain); + + if (connection == NULL) { + VPN_LOG(VPN_ERROR, "host=%s domain=%s", host, domain); + return VPN_ERROR_INVALID_PARAMETER; + } + + *handle = connection; + return VPN_ERROR_NONE; +} + +/* + * Get VPN Info (Name) from VPN Handle + */ +int _vpn_get_vpn_info_name(vpn_h handle, const char **name) +{ + VPN_LOG(VPN_INFO, ""); + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + *name = vpn_connection_get_name(handle); + return VPN_ERROR_NONE; +} + +/* + * Get VPN Info (Type) from VPN Handle + */ +int _vpn_get_vpn_info_type(vpn_h handle, const char **type) +{ + VPN_LOG(VPN_INFO, ""); + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + *type = vpn_connection_get_type(handle); + return VPN_ERROR_NONE; +} + +/* + * Get VPN Info (Host) from VPN Handle + */ +int _vpn_get_vpn_info_host(vpn_h handle, const char **host) +{ + VPN_LOG(VPN_INFO, ""); + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + *host = vpn_connection_get_host(handle); + return VPN_ERROR_NONE; +} + +/* + * Get VPN Info (Domain) from VPN Handle + */ +int _vpn_get_vpn_info_domain(vpn_h handle, const char **domain) +{ + VPN_LOG(VPN_INFO, ""); + + GList *connections = vpn_get_connections(); + if (NULL == g_list_find(connections, handle)) { + VPN_LOG(VPN_ERROR, "No Connections with the %p Handle", handle); + return VPN_ERROR_INVALID_PARAMETER; + } + + *domain = vpn_connection_get_domain(handle); + return VPN_ERROR_NONE; +} diff --git a/src/vpn.c b/src/vpn.c new file mode 100644 index 0000000..ec45d53 --- /dev/null +++ b/src/vpn.c @@ -0,0 +1,388 @@ +/* +* Network VPN library +* +* Copyright (c) 2014-2015 Samsung Electronics. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + +#include +#include +#include +#include + +#include "vpn-internal.h" + +static bool is_init = false; + +EXPORT_API int vpn_initialize(void) +{ + if (is_init) { + VPN_LOG(VPN_ERROR, "Already initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (_vpn_init() == false) { + VPN_LOG(VPN_ERROR, "Init failed!\n"); + return VPN_ERROR_OPERATION_FAILED; + } + + is_init = true; + + VPN_LOG(VPN_INFO, "VPN successfully initialized!\n"); + + return VPN_ERROR_NONE; +} + +EXPORT_API int vpn_deinitialize(void) +{ + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (_vpn_deinit() == false) { + VPN_LOG(VPN_ERROR, "Deinit failed!\n"); + return VPN_ERROR_OPERATION_FAILED; + } + + is_init = false; + VPN_LOG(VPN_INFO, "VPN successfully de-initialized!\n"); + + return VPN_ERROR_NONE; +} + +/* Settings API's */ +EXPORT_API int vpn_settings_init() +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_init(); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_settings_deinit() +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_deinit(); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_settings_set_specific(const char *key, const char *value) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_set_specific(key, value); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + + +EXPORT_API int vpn_settings_set_type(const char *type) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_set_specific("Type", type); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_settings_set_name(const char *name) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_set_specific("Name", name); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_settings_set_host(const char *host) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_set_specific("Host", host); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_settings_set_domain(const char *domain) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_settings_set_specific("Domain", domain); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Settings Deinit failed.\n"); + + return rv; +} + +EXPORT_API int vpn_create(vpn_created_cb callback, void *user_data) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + rv = _vpn_create(callback, user_data); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Create failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_remove(vpn_h handle, vpn_removed_cb callback, void *user_data) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL) { + VPN_LOG(VPN_ERROR, "VPN Handle is NULL\n"); + return VPN_ERROR_INVALID_PARAMETER; + } + + rv = _vpn_remove(handle, callback, user_data); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Remove failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_connect(vpn_h handle, vpn_connect_cb callback, void *user_data) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL) { + VPN_LOG(VPN_ERROR, "VPN Handle is NULL\n"); + return VPN_ERROR_INVALID_PARAMETER; + } + + rv = _vpn_connect(handle, callback, user_data); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Remove failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_disconnect(vpn_h handle, vpn_disconnect_cb callback, void *user_data) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL) { + VPN_LOG(VPN_ERROR, "VPN Handle is NULL\n"); + return VPN_ERROR_INVALID_PARAMETER; + } + + rv = _vpn_disconnect(handle); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Remove failed.\n"); + + return rv; +} + +EXPORT_API +GList *vpn_get_vpn_handle_list(void) +{ + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return NULL; + } + + return _vpn_get_vpn_handle_list(); +} + +EXPORT_API +int vpn_get_vpn_handle(const char *host, const char *domain, vpn_h *handle) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (host == NULL || domain == NULL || handle == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + rv = _vpn_get_vpn_handle(host, domain, handle); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Get Handle failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_get_vpn_info_name(const vpn_h handle, const char **name) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL || name == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + rv = _vpn_get_vpn_info_name(handle, name); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Get Info (Name) failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_get_vpn_info_type(const vpn_h handle, const char **type) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL || type == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + rv = _vpn_get_vpn_info_type(handle, type); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Get Info (Type) failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_get_vpn_info_host(const vpn_h handle, const char **host) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL || host == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + rv = _vpn_get_vpn_info_host(handle, host); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Get Info (Host) failed.\n"); + + return rv; +} + +EXPORT_API +int vpn_get_vpn_info_domain(const vpn_h handle, const char **domain) +{ + int rv; + + if (is_init == false) { + VPN_LOG(VPN_ERROR, "Not initialized\n"); + return VPN_ERROR_INVALID_OPERATION; + } + + if (handle == NULL || domain == NULL) + return VPN_ERROR_INVALID_PARAMETER; + + rv = _vpn_get_vpn_info_domain(handle, domain); + + if (rv != VPN_ERROR_NONE) + VPN_LOG(VPN_ERROR, "Error!! VPN Get Info (Domain) failed.\n"); + + return rv; +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..1ff2267 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,20 @@ +SET(fw_test "capi-vpn-test") + +SET(dependents "capi-base-common glib-2.0") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_test} REQUIRED ${dependents}) +FOREACH(flag ${${fw_test}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall") + +aux_source_directory(. sources) +FOREACH(src ${sources}) + GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) + MESSAGE("${fw_test}") + ADD_EXECUTABLE(${fw_test} ${src}) + TARGET_LINK_LIBRARIES(${fw_test} ${fw_name} ${${fw_test}_LDFLAGS}) + INSTALL(TARGETS ${fw_test} DESTINATION ${LIB_INSTALL_DIR}/vpn-capi-test/) +ENDFOREACH() diff --git a/test/vpn_test.c b/test/vpn_test.c new file mode 100644 index 0000000..3ee6009 --- /dev/null +++ b/test/vpn_test.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +gboolean test_thread(GIOChannel *source, + GIOCondition condition, + gpointer data); + +static const char *__test_convert_error_to_string(vpn_error_e err_type) +{ + switch (err_type) { + case VPN_ERROR_NONE: + return "NONE"; + case VPN_ERROR_INVALID_PARAMETER: + return "INVALID_PARAMETER"; + case VPN_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case VPN_ERROR_INVALID_OPERATION: + return "INVALID_OPERATION"; + case VPN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED: + return "ADDRESS_FAMILY_NOT_SUPPORTED"; + case VPN_ERROR_OPERATION_FAILED: + return "OPERATION_FAILED"; + case VPN_ERROR_NO_CONNECTION: + return "NO_CONNECTION"; + case VPN_ERROR_NOW_IN_PROGRESS: + return "NOW_IN_PROGRESS"; + case VPN_ERROR_ALREADY_EXISTS: + return "ALREADY_EXISTS"; + case VPN_ERROR_OPERATION_ABORTED: + return "OPERATION_ABORTED"; + case VPN_ERROR_DHCP_FAILED: + return "DHCP_FAILED"; + case VPN_ERROR_INVALID_KEY: + return "INVALID_KEY"; + case VPN_ERROR_NO_REPLY: + return "NO_REPLY"; + case VPN_ERROR_SECURITY_RESTRICTED: + return "SECURITY_RESTRICTED"; + } + + return "UNKNOWN"; +} + +static void __test_created_callback(vpn_error_e result, + void *user_data) +{ + if (result == VPN_ERROR_NONE) + printf("VPN Create Succeeded\n"); + else + printf("VPN Create Failed! error : %s", + __test_convert_error_to_string(result)); +} + +static void __test_removed_callback(vpn_error_e result, + void *user_data) +{ + if (result == VPN_ERROR_NONE) + printf("VPN Remove Succeeded\n"); + else + printf("VPN Remove Failed! error : %s", + __test_convert_error_to_string(result)); +} + +static void __test_connect_callback(vpn_error_e result, + void *user_data) +{ + if (result == VPN_ERROR_NONE) + printf("VPN Connect Succeeded\n"); + else + printf("VPN Connect Failed! error : %s", + __test_convert_error_to_string(result)); +} + +static void __test_disconnect_callback(vpn_error_e result, + void *user_data) +{ + if (result == VPN_ERROR_NONE) + printf("VPN Disconnect Succeeded\n"); + else + printf("VPN Disconnect Failed! error : %s", + __test_convert_error_to_string(result)); +} + +static void _test_get_vpn_handle(vpn_h *handle_ptr) +{ + assert(handle_ptr != NULL); + + char host_str[128] = { 0 }; + char domain_str[128] = { 0 }; + const char *name = NULL; + const char *type = NULL; + const char *host = NULL; + const char *domain = NULL; + + GList *iter; + GList *handles = vpn_get_vpn_handle_list(); + for (iter = handles; iter != NULL; iter = iter->next) { + printf("\n Handle = %p\n", iter->data); + vpn_get_vpn_info_name(iter->data, &name); + vpn_get_vpn_info_type(iter->data, &type); + vpn_get_vpn_info_host(iter->data, &host); + vpn_get_vpn_info_domain(iter->data, &domain); + printf(" Name[%p] - %s\n", iter->data, name); + printf(" Type[%p] - %s\n", iter->data, type); + printf(" Host[%p] - %s\n", iter->data, host); + printf(" Domain[%p] - %s\n", iter->data, domain); + } + + printf("==================================\n"); + printf(" Please ENTER Host: "); + if (scanf(" %s", host_str) < 0) + printf("Error in Reading Host String\n"); + + printf(" Please ENTER Domain: "); + if (scanf(" %s", domain_str) < 0) + printf("Error in Reading Domain String\n"); + + vpn_get_vpn_handle(host_str, domain_str, handle_ptr); +} + +static void _test_get_user_input(char *buf, char *what) +{ + printf("Please ENTER %s:", what); + if (scanf(" %[^\n]s", buf) < 0) { + printf("Error in Reading the data to Buffer\n"); + } +} + +int test_vpn_init(void) +{ + int rv = vpn_initialize(); + + if (rv == VPN_ERROR_NONE) { + printf("Register Callbacks if Initialize is Successful\n"); + } else { + printf("VPN init failed [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("VPN init succeeded\n"); + return 1; +} + +int test_vpn_deinit(void) +{ + int rv = vpn_deinitialize(); + + if (rv != VPN_ERROR_NONE) { + printf("VPN init failed [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("VPN deinit succeeded\n"); + return 1; +} + +int test_vpn_settings_init(void) +{ + int rv = 0; + + rv = vpn_settings_init(); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Initialize Settings [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success Creating Settings API's\n"); + + return 1; +} + +int test_vpn_settings_add(void) +{ + int rv = 0; + char buf[100]; + + _test_get_user_input(&buf[0], "Type"); + rv = vpn_settings_set_type(&buf[0]); + if (rv != VPN_ERROR_NONE) { + printf("Fail to VPN Settings Type[%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + _test_get_user_input(&buf[0], "Name"); + rv = vpn_settings_set_name(&buf[0]); + if (rv != VPN_ERROR_NONE) { + printf("Fail to VPN Settings Name[%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + _test_get_user_input(&buf[0], "Host"); + rv = vpn_settings_set_host(&buf[0]); + if (rv != VPN_ERROR_NONE) { + printf("Fail to VPN Settings Host[%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + _test_get_user_input(&buf[0], "Domain"); + rv = vpn_settings_set_domain(&buf[0]); + if (rv != VPN_ERROR_NONE) { + printf("Fail to VPN Settings Domain[%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success Creating Settings API's\n"); + + return 1; +} + +int test_vpn_settings_deinit(void) +{ + int rv = 0; + + rv = vpn_settings_deinit(); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Deinitialize Settings [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success Deleting Settings API's\n"); + + return 1; +} + +int test_vpn_settings_set_specific(void) +{ + int rv = 0; + char key[100]; + char value[200]; + + _test_get_user_input(&key[0], "Key"); + _test_get_user_input(&value[0], "Value"); + rv = vpn_settings_set_specific(&key[0], &value[0]); + if (rv != VPN_ERROR_NONE) { + printf("Fail to Set Specific VPN Settings %s[%s]\n", + key, __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success in VPN Settings Add %s=%s\n", key, value); + + return 1; +} + +int test_vpn_create(void) +{ + int rv = 0; + + rv = vpn_create(__test_created_callback, NULL); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Create VPN Profile [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success to Create VPN Profile\n"); + + return 1; +} + +int test_vpn_remove(void) +{ + int rv = 0; + + /*TODO: Get the List of VPN Profiles Identifiers + * Prompt user to which one to be deleted */ + + rv = vpn_remove(NULL, __test_removed_callback, NULL); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Remove VPN Profile [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success to Remove VPN Profile\n"); + + return 1; +} + +int test_vpn_connect(void) +{ + int rv = 0; + vpn_h handle = NULL; + + _test_get_vpn_handle(&handle); + + rv = vpn_connect(handle, __test_connect_callback, NULL); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Connect to VPN Profile [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success to Connect VPN Profile\n"); + + return 1; +} + +int test_vpn_disconnect(void) +{ + int rv = 0; + vpn_h handle = NULL; + + _test_get_vpn_handle(&handle); + + rv = vpn_disconnect(handle, __test_disconnect_callback, NULL); + + if (rv != VPN_ERROR_NONE) { + printf("Fail to Disconnect from VPN Profile [%s]\n", + __test_convert_error_to_string(rv)); + return -1; + } + + printf("Success to Disconnect VPN Profile\n"); + + return 1; +} + +int main(int argc, char **argv) +{ + GMainLoop *mainloop; + mainloop = g_main_loop_new(NULL, FALSE); + + GIOChannel *channel = g_io_channel_unix_new(0); + g_io_add_watch(channel, (G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL), + test_thread, NULL); + + printf("Test Thread created...\n"); + + g_main_loop_run(mainloop); + + return 0; +} + +gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) +{ + int rv; + char a[10]; + + printf("Event received from stdin\n"); + + rv = read(0, a, 10); + + if (rv <= 0 || a[0] == '0') { + rv = vpn_deinitialize(); + + if (rv != VPN_ERROR_NONE) + printf("Fail to deinitialize.\n"); + + exit(1); + } + + if (a[0] == '\n' || a[0] == '\r') { + printf("\n\n Network Connection API Test App\n\n"); + printf("Options..\n"); + printf("1\t- VPN init and set callbacks\n"); + printf("2\t- VPN deinit(unset callbacks automatically)\n"); + printf("3\t- VPN Settings Initialize - Initialize Settings for Creating a VPN profile\n"); + printf("4\t- VPN Settings Delete - Delete Settings VPN profile\n"); + printf("5\t- VPN Settings Set Specific - Allows to add a specific setting\n"); + printf("6\t- VPN Settings Add - Add Type,Host,Name,Domain settings\n"); + printf("7\t- VPN Create - Creates the VPN profile\n"); + printf("8\t- VPN Remove - Removes the VPN profile\n"); + printf("9\t- VPN Connect - Connect the VPN profile\n"); + printf("a\t- VPN Disconnect - Disconnect the VPN profile\n"); + printf("0\t- Exit\n"); + + printf("ENTER - Show options menu.......\n"); + } + + switch (a[0]) { + case '1': + rv = test_vpn_init(); + break; + case '2': + rv = test_vpn_deinit(); + break; + case '3': + rv = test_vpn_settings_init(); + break; + case '4': + rv = test_vpn_settings_deinit(); + break; + case '5': + rv = test_vpn_settings_set_specific(); + break; + case '6': + rv = test_vpn_settings_add(); + break; + case '7': + rv = test_vpn_create(); + break; + case '8': + rv = test_vpn_remove(); + break; + case '9': + rv = test_vpn_connect(); + break; + case 'a': + rv = test_vpn_disconnect(); + break; + default: + break; + } + + if (rv == 1) + printf("Operation succeeded!\n"); + else + printf("Operation failed!\n"); + + return TRUE; +} + + -- 2.34.1