Send connman mailing list submissions to
        connman@lists.01.org

To subscribe or unsubscribe via email, send a message with subject or
body 'help' to
        connman-requ...@lists.01.org

You can reach the person managing the list at
        connman-ow...@lists.01.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."

Today's Topics:

   1. [PATCH 12/15] vpn-config: Implement function to get boolean from keyfile
      (Jussi Laakkonen)
   2. [PATCH 13/15] vpn-provider: Drop route management from vpnd
      (Jussi Laakkonen)
   3. [PATCH 14/15] vpn-provider: Support SplitRouting option from connmand
      (Jussi Laakkonen)
   4. [PATCH 15/15] doc: Document VPN connection SplitRouting boolean
      (Jussi Laakkonen)


----------------------------------------------------------------------

Date: Tue,  8 Dec 2020 12:17:58 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 12/15] vpn-config: Implement function to get boolean
        from keyfile
To: connman@lists.01.org
Message-ID: <20201208101801.26715-13-jussi.laakko...@jolla.com>

Simple boolean getter for VPN keyfiles. In case of error (key missing or
invalid boolean) the default value given is returned.
---
 vpn/vpn-config.c | 15 +++++++++++++++
 vpn/vpn.h        | 10 ++++++----
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/vpn/vpn-config.c b/vpn/vpn-config.c
index 301243b5..8c6b0681 100644
--- a/vpn/vpn-config.c
+++ b/vpn/vpn-config.c
@@ -580,3 +580,18 @@ char **__vpn_config_get_string_list(GKeyFile *key_file,
 
        return strlist;
 }
+
+bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+                       const char *key, bool default_value)
+{
+       GError *error = NULL;
+       bool val;
+
+       val = g_key_file_get_boolean(key_file, group_name, key, &error);
+       if (error) {
+               g_error_free(error);
+               return default_value;
+       }
+
+       return val;
+}
diff --git a/vpn/vpn.h b/vpn/vpn.h
index 8d7c63d6..9649f545 100644
--- a/vpn/vpn.h
+++ b/vpn/vpn.h
@@ -111,10 +111,12 @@ int __vpn_rtnl_send(const void *buf, size_t len);
 
 int __vpn_config_init(void);
 void __vpn_config_cleanup(void);
-char *__vpn_config_get_string(GKeyFile *key_file,
-        const char *group_name, const char *key, GError **error);
-char **__vpn_config_get_string_list(GKeyFile *key_file,
-        const char *group_name, const char *key, gsize *length, GError 
**error);
+char *__vpn_config_get_string(GKeyFile *key_file, const char *group_name,
+                                       const char *key, GError **error);
+char **__vpn_config_get_string_list(GKeyFile *key_file, const char *group_name,
+                       const char *key, gsize *length, GError **error);
+bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+                       const char *key, bool default_value);
 
 int __vpn_settings_init(const char *file);
 void __vpn_settings_cleanup(void);
-- 
2.20.1

------------------------------

Date: Tue,  8 Dec 2020 12:17:59 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 13/15] vpn-provider: Drop route management from vpnd
To: connman@lists.01.org
Message-ID: <20201208101801.26715-14-jussi.laakko...@jolla.com>

This change removes the '-r' option to toggle whether to manage routes
or not in connman-vpnd. Remove all functionality from vpn-provider.c
that was used for managing routes. Remove all functions managing the
routes. All routes should be managed by connmand only.

The change was suggested by Daniel Wagner on the mailing list:
https://lists.01.org/hyperkitty/list/connman@lists.01.org/message/
YTSQ636O7GROD4NZH6B4AVQMTO6SN3QO/. The change was originally
introduced in a7851eb04e67a6c046c1665157a97fd6b2d42462 for the most
part.
---
 doc/connman-vpn.8.in |  4 --
 vpn/main.c           |  5 +--
 vpn/vpn-provider.c   | 99 ++++----------------------------------------
 vpn/vpn-provider.h   |  3 ++
 vpn/vpn.h            |  2 +-
 5 files changed, 13 insertions(+), 100 deletions(-)

diff --git a/doc/connman-vpn.8.in b/doc/connman-vpn.8.in
index 6130b3b8..829c4983 100644
--- a/doc/connman-vpn.8.in
+++ b/doc/connman-vpn.8.in
@@ -19,7 +19,6 @@ ConnMan-VPN \- VPN management daemon
 .RB [\| \-P
 .IR plugin [,...]\|]
 .RB [\| \-n \|]
-.RB [\| \-r \|]
 .SH DESCRIPTION
 The \fIConnMan-VPN\fP provides a daemon for managing vpn connections together
 with \fBconnmand\fP(8). The Connection Manager is designed to be slim and to
@@ -54,9 +53,6 @@ present, then only debug prints from that source file are 
printed. Example:
 .BR \-n ", " \-\-nodaemon
 Do not daemonize. This is useful for debugging, and directs log output to
 the controlling terminal in addition to syslog.
-.TP
-.BR \-r ", " \-\-routes
-Manage VPN routes instead of telling \fBconnmand\fP(8) to do it.
 .SH SEE ALSO
 .BR connmanctl (1), \ connman-vpn.conf (5), \c
 .BR \ connman-vpn-provider.config (5), \ connmand (8)
diff --git a/vpn/main.c b/vpn/main.c
index 133acd27..92c63e20 100644
--- a/vpn/main.c
+++ b/vpn/main.c
@@ -129,7 +129,6 @@ static gchar *option_plugin = NULL;
 static gchar *option_noplugin = NULL;
 static bool option_detach = true;
 static bool option_version = false;
-static bool option_routes = false;
 
 static bool parse_debug(const char *key, const char *value,
                                        gpointer user_data, GError **error)
@@ -156,8 +155,6 @@ static GOptionEntry options[] = {
        { "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_detach,
                                "Don't fork daemon to background" },
-       { "routes", 'r', 0, G_OPTION_ARG_NONE, &option_routes,
-                               "Create/delete VPN routes" },
        { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
                                "Show version information and exit" },
        { NULL },
@@ -259,7 +256,7 @@ int main(int argc, char *argv[])
 
        __connman_inotify_init();
        __connman_agent_init();
-       __vpn_provider_init(option_routes);
+       __vpn_provider_init();
        __vpn_manager_init();
        __vpn_ipconfig_init();
        __vpn_rtnl_init();
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index 08728c8c..8a7d82fc 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -44,7 +44,6 @@ static DBusConnection *connection;
 static GHashTable *provider_hash;
 static GSList *driver_list;
 static int configuration_count;
-static bool handle_routes;
 
 struct vpn_route {
        int family;
@@ -366,22 +365,8 @@ static void set_user_networks(struct vpn_provider 
*provider, GSList *networks)
 static void del_routes(struct vpn_provider *provider)
 {
        GHashTableIter hash;
-       gpointer value, key;
 
        g_hash_table_iter_init(&hash, provider->user_routes);
-       while (handle_routes && g_hash_table_iter_next(&hash,
-                                               &key, &value)) {
-               struct vpn_route *route = value;
-               if (route->family == AF_INET6) {
-                       unsigned char prefixlen = atoi(route->netmask);
-                       connman_inet_del_ipv6_network_route(provider->index,
-                                                       route->network,
-                                                       prefixlen);
-               } else
-                       connman_inet_del_host_route(provider->index,
-                                               route->network);
-       }
-
        g_hash_table_remove_all(provider->user_routes);
        g_slist_free_full(provider->user_networks, free_route);
        provider->user_networks = NULL;
@@ -500,10 +485,7 @@ static int set_provider_property(struct vpn_provider 
*provider,
                del_routes(provider);
                provider->user_networks = networks;
                set_user_networks(provider, provider->user_networks);
-
-               if (!handle_routes)
-                       send_routes(provider, provider->user_routes,
-                                               "UserRoutes");
+               send_routes(provider, provider->user_routes, "UserRoutes");
        } else {
                const char *str;
 
@@ -702,8 +684,7 @@ static DBusMessage *clear_property(DBusConnection *conn, 
DBusMessage *msg,
 
                del_routes(provider);
 
-               if (!handle_routes)
-                       send_routes(provider, provider->user_routes, name);
+               send_routes(provider, provider->user_routes, name);
        } else if (vpn_provider_get_string(provider, name)) {
                err = vpn_provider_set_string(provider, name, NULL);
                switch (err) {
@@ -1007,18 +988,17 @@ static int provider_load_from_keyfile(struct 
vpn_provider *provider,
                                                &num_user_networks,
                                                NULL);
                                provider->user_networks = get_routes(networks);
-
                        } else {
                                value = __vpn_config_get_string(keyfile,
                                                        provider->identifier,
                                                        key, NULL);
-                               vpn_provider_set_string(provider, key,
-                                                       value);
+                               vpn_provider_set_string(provider, key, value);
                                g_free(value);
                        }
                }
                idx += 1;
        }
+
        g_strfreev(settings);
        g_strfreev(networks);
 
@@ -1135,6 +1115,7 @@ static int vpn_provider_save(struct vpn_provider 
*provider)
                        "Host", provider->host);
        g_key_file_set_string(keyfile, provider->identifier,
                        "VPN.Domain", provider->domain);
+
        if (provider->user_networks) {
                gchar **networks;
                gsize network_count;
@@ -1806,55 +1787,6 @@ static void connection_added_signal(struct vpn_provider 
*provider)
        dbus_message_unref(signal);
 }
 
-static bool check_host(char **hosts, char *host)
-{
-       int i;
-
-       if (!hosts)
-               return false;
-
-       for (i = 0; hosts[i]; i++) {
-               if (g_strcmp0(hosts[i], host) == 0)
-                       return true;
-       }
-
-       return false;
-}
-
-static void provider_append_routes(gpointer key, gpointer value,
-                                       gpointer user_data)
-{
-       struct vpn_route *route = value;
-       struct vpn_provider *provider = user_data;
-       int index = provider->index;
-
-       if (!handle_routes)
-               return;
-
-       /*
-        * If the VPN administrator/user has given a route to
-        * VPN server, then we must discard that because the
-        * server cannot be contacted via VPN tunnel.
-        */
-       if (check_host(provider->host_ip, route->network)) {
-               DBG("Discarding VPN route to %s via %s at index %d",
-                       route->network, route->gateway, index);
-               return;
-       }
-
-       if (route->family == AF_INET6) {
-               unsigned char prefix_len = atoi(route->netmask);
-
-               connman_inet_add_ipv6_network_route(index, route->network,
-                                                       route->gateway,
-                                                       prefix_len);
-       } else {
-               connman_inet_add_network_route(index, route->network,
-                                               route->gateway,
-                                               route->netmask);
-       }
-}
-
 static int set_connected(struct vpn_provider *provider,
                                        bool connected)
 {
@@ -1871,18 +1803,8 @@ static int set_connected(struct vpn_provider *provider,
 
                __vpn_ipconfig_address_add(ipconfig, provider->family);
 
-               if (handle_routes)
-                       __vpn_ipconfig_gateway_add(ipconfig, provider->family);
-
                provider_indicate_state(provider,
                                        VPN_PROVIDER_STATE_READY);
-
-               g_hash_table_foreach(provider->routes, provider_append_routes,
-                                       provider);
-
-               g_hash_table_foreach(provider->user_routes,
-                                       provider_append_routes, provider);
-
        } else {
                provider_indicate_state(provider,
                                        VPN_PROVIDER_STATE_DISCONNECT);
@@ -2921,11 +2843,8 @@ int vpn_provider_append_route(struct vpn_provider 
*provider,
                break;
        }
 
-       if (!handle_routes) {
-               if (route->netmask && route->gateway &&
-                                                       route->network)
-                       provider_schedule_changed(provider);
-       }
+       if (route->netmask && route->gateway && route->network)
+               provider_schedule_changed(provider);
 
        return 0;
 }
@@ -3158,14 +3077,12 @@ static void remove_unprovisioned_providers(void)
        g_strfreev(providers);
 }
 
-int __vpn_provider_init(bool do_routes)
+int __vpn_provider_init(void)
 {
        int err;
 
        DBG("");
 
-       handle_routes = do_routes;
-
        err = connman_agent_driver_register(&agent_driver);
        if (err < 0) {
                connman_error("Cannot register agent driver for %s",
diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h
index d2627847..f7fa8591 100644
--- a/vpn/vpn-provider.h
+++ b/vpn/vpn-provider.h
@@ -83,6 +83,9 @@ const char *vpn_provider_get_string(struct vpn_provider 
*provider,
                                                        const char *key);
 bool vpn_provider_get_string_immutable(struct vpn_provider *provider,
                                                        const char *key);
+int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+                                                       bool value,
+                                                       bool force_change);
 bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
                                                        bool default_value);
 
diff --git a/vpn/vpn.h b/vpn/vpn.h
index 9649f545..fa968f60 100644
--- a/vpn/vpn.h
+++ b/vpn/vpn.h
@@ -96,7 +96,7 @@ int __vpn_provider_disconnect(struct vpn_provider *provider);
 int __vpn_provider_remove(const char *path);
 int __vpn_provider_delete(struct vpn_provider *provider);
 void __vpn_provider_cleanup(void);
-int __vpn_provider_init(bool handle_routes);
+int __vpn_provider_init();
 
 #include "vpn-rtnl.h"
 
-- 
2.20.1

------------------------------

Date: Tue,  8 Dec 2020 12:18:00 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 14/15] vpn-provider: Support SplitRouting option from
        connmand
To: connman@lists.01.org
Message-ID: <20201208101801.26715-15-jussi.laakko...@jolla.com>

Support SplitRouting option in vpnd. The value is passed as
boolean and a warning is printed with invalid error if attempted to
be set as string. For setting the boolean values in provider settings
vpn_provider_set_boolean() is added.

Implement provider_property_changed() to be registered with every call
to connect_provider() for the signals sent about property changes on
VPN services. React only to "SplitRouting" value changes coming from
the VPN service via connmand.

Also always notify all components listening for the changes over VPN
D-Bus API on SplitRouting changes coming from connmand. The signal will
be reacted upon also by connmand but provider.c will ignore setting of
the same value to avoid D-Bus signal loop. For this the
vpn_provider_add_boolean() is modified to have an option to have th
signal sending forced regardless of the value change. This is required
for notifying the components listening for the changes via VPN D-Bus API
when connmand/connman-vpnd crashes and the value is not written yet to
the VPN service settings file and the component would not get an update,
for example, to "true" value it has if connmand and vpnd have false (by
default, vpnd has the value as false). There are duplicate signals sent
but this approach ensures that all components will know the correct
status of SplitRouting.

Do some minor cleanups to code in order to support code syntax.
---
 vpn/vpn-provider.c | 179 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 158 insertions(+), 21 deletions(-)

diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index 8a7d82fc..59c805c5 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -70,6 +70,7 @@ struct vpn_provider {
        char *host;
        char *domain;
        int family;
+       bool do_split_routing;
        GHashTable *routes;
        struct vpn_provider_driver *driver;
        void *driver_data;
@@ -90,6 +91,7 @@ struct vpn_provider {
        void *plugin_data;
        unsigned int auth_error_counter;
        unsigned int conn_error_counter;
+       unsigned int signal_watch;
 };
 
 static void append_properties(DBusMessageIter *iter,
@@ -389,6 +391,16 @@ static void send_value(const char *path, const char *key, 
const char *value)
                                        &str);
 }
 
+static void send_value_boolean(const char *path, const char *key,
+                                                       dbus_bool_t value)
+{
+       connman_dbus_property_changed_basic(path,
+                                       VPN_CONNECTION_INTERFACE,
+                                       key,
+                                       DBUS_TYPE_BOOLEAN,
+                                       &value);
+}
+
 static gboolean provider_send_changed(gpointer data)
 {
        struct vpn_provider *provider = data;
@@ -459,6 +471,11 @@ static bool compare_network_lists(GSList *a, GSList *b)
        return true;
 }
 
+static const char *bool2str(bool value)
+{
+       return value ? "true" : "false";
+}
+
 static int set_provider_property(struct vpn_provider *provider,
                        const char *name, DBusMessageIter *value, int type)
 {
@@ -486,6 +503,16 @@ static int set_provider_property(struct vpn_provider 
*provider,
                provider->user_networks = networks;
                set_user_networks(provider, provider->user_networks);
                send_routes(provider, provider->user_routes, "UserRoutes");
+       } else if (g_str_equal(name, "SplitRouting")) {
+               dbus_bool_t split_routing;
+
+               if (type != DBUS_TYPE_BOOLEAN)
+                       return -EINVAL;
+
+               dbus_message_iter_get_basic(value, &split_routing);
+
+               DBG("property %s value %s ", name, bool2str(split_routing));
+               vpn_provider_set_boolean(provider, name, split_routing, false);
        } else {
                const char *str;
 
@@ -558,8 +585,13 @@ static DBusMessage *set_properties(DBusMessageIter *iter, 
DBusMessage *msg,
                dbus_message_iter_recurse(&entry, &value);
 
                type = dbus_message_iter_get_arg_type(&value);
-               /* Ignore and report back all invalid property types */
-               if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_ARRAY) {
+               switch (type) {
+               case DBUS_TYPE_STRING:
+               case DBUS_TYPE_ARRAY:
+               case DBUS_TYPE_BOOLEAN:
+                       break;
+               default:
+                       /* Ignore and report back all invalid property types */
                        invalid = append_to_gstring(invalid, key);
                        continue;
                }
@@ -822,6 +854,8 @@ static void provider_resolv_host_addr(struct vpn_provider 
*provider)
 void __vpn_provider_append_properties(struct vpn_provider *provider,
                                                        DBusMessageIter *iter)
 {
+       dbus_bool_t split_routing;
+
        if (provider->host)
                connman_dbus_dict_append_basic(iter, "Host",
                                        DBUS_TYPE_STRING, &provider->host);
@@ -833,6 +867,10 @@ void __vpn_provider_append_properties(struct vpn_provider 
*provider,
        if (provider->type)
                connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
                                                 &provider->type);
+
+       split_routing = provider->do_split_routing;
+       connman_dbus_dict_append_basic(iter, "SplitRouting", DBUS_TYPE_BOOLEAN,
+                                                       &split_routing);
 }
 
 int __vpn_provider_append_user_route(struct vpn_provider *provider,
@@ -965,7 +1003,7 @@ static GSList *get_routes(gchar **networks)
 static int provider_load_from_keyfile(struct vpn_provider *provider,
                GKeyFile *keyfile)
 {
-       gsize idx = 0;
+       gsize idx;
        gchar **settings;
        gchar *key, *value;
        gsize length, num_user_networks;
@@ -978,25 +1016,24 @@ static int provider_load_from_keyfile(struct 
vpn_provider *provider,
                return -ENOENT;
        }
 
-       while (idx < length) {
+       for (idx = 0; idx < length; idx++) {
                key = settings[idx];
-               if (key) {
-                       if (g_str_equal(key, "Networks")) {
-                               networks = __vpn_config_get_string_list(keyfile,
-                                               provider->identifier,
-                                               key,
-                                               &num_user_networks,
+               if (!key)
+                       continue;
+
+               if (g_str_equal(key, "Networks")) {
+                       networks = __vpn_config_get_string_list(keyfile,
+                                               provider->identifier,key,
+                                               &num_user_networks, NULL);
+                       provider->user_networks = get_routes(networks);
+               } else {
+                       value = __vpn_config_get_string(keyfile,
+                                               provider->identifier, key,
                                                NULL);
-                               provider->user_networks = get_routes(networks);
-                       } else {
-                               value = __vpn_config_get_string(keyfile,
-                                                       provider->identifier,
-                                                       key, NULL);
-                               vpn_provider_set_string(provider, key, value);
-                               g_free(value);
-                       }
+
+                       vpn_provider_set_string(provider, key, value);
+                       g_free(value);
                }
-               idx += 1;
        }
 
        g_strfreev(settings);
@@ -1706,6 +1743,7 @@ static void append_properties(DBusMessageIter *iter,
        GHashTableIter hash;
        gpointer value, key;
        dbus_bool_t immutable;
+       dbus_bool_t split_routing;
 
        connman_dbus_dict_open(iter, &dict);
 
@@ -1733,6 +1771,10 @@ static void append_properties(DBusMessageIter *iter,
        connman_dbus_dict_append_basic(&dict, "Immutable", DBUS_TYPE_BOOLEAN,
                                        &immutable);
 
+       split_routing = provider->do_split_routing;
+       connman_dbus_dict_append_basic(&dict, "SplitRouting",
+                                       DBUS_TYPE_BOOLEAN, &split_routing);
+
        if (provider->family == AF_INET)
                connman_dbus_dict_append_dict(&dict, "IPv4", append_ipv4,
                                                provider);
@@ -1757,8 +1799,7 @@ static void append_properties(DBusMessageIter *iter,
                while (g_hash_table_iter_next(&hash, &key, &value)) {
                        struct vpn_setting *setting = value;
 
-                       if (!setting->hide_value &&
-                                                       setting->value)
+                       if (!setting->hide_value && setting->value)
                                connman_dbus_dict_append_basic(&dict, key,
                                                        DBUS_TYPE_STRING,
                                                        &setting->value);
@@ -1871,10 +1912,61 @@ int vpn_provider_indicate_error(struct vpn_provider 
*provider,
        return 0;
 }
 
+static gboolean provider_property_changed(DBusConnection *conn,
+                                       DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       DBusMessageIter value;
+       struct vpn_provider *provider = user_data;
+       const char *key;
+
+       if (!dbus_message_iter_init(message, &iter))
+               return TRUE;
+
+       dbus_message_iter_get_basic(&iter, &key);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &value);
+
+       DBG("provider %p key %s", provider, key);
+
+       if (g_str_equal(key, "SplitRouting")) {
+               dbus_bool_t split_routing;
+
+               if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_BOOLEAN)
+                       goto out;
+
+               dbus_message_iter_get_basic(&value, &split_routing);
+
+               DBG("property %s value %s", key, bool2str(split_routing));
+
+               /*
+                * Even though this is coming from connmand, signal the value
+                * for other components listening to the changes via VPN API
+                * only. provider.c will skip setting the same value in order
+                * to avoid signaling loop. This is needed for ensuring that
+                * all components using VPN API will be informed about the
+                * correct status of SplitRouting. Especially when loading the
+                * services after a crash, for instance.
+                */
+               vpn_provider_set_boolean(provider, "SplitRouting",
+                                       split_routing, true);
+       }
+
+out:
+       return TRUE;
+}
+
 static int connection_unregister(struct vpn_provider *provider)
 {
        DBG("provider %p path %s", provider, provider->path);
 
+       if (provider->signal_watch) {
+               g_dbus_remove_watch(connection, provider->signal_watch);
+               provider->signal_watch = 0;
+       }
+
        if (!provider->path)
                return -EALREADY;
 
@@ -1889,6 +1981,8 @@ static int connection_unregister(struct vpn_provider 
*provider)
 
 static int connection_register(struct vpn_provider *provider)
 {
+       char *connmand_vpn_path;
+
        DBG("provider %p path %s", provider, provider->path);
 
        if (provider->path)
@@ -1902,6 +1996,18 @@ static int connection_register(struct vpn_provider 
*provider)
                                connection_methods, connection_signals,
                                NULL, provider, NULL);
 
+       connmand_vpn_path = g_strdup_printf("%s/service/vpn_%s", CONNMAN_PATH,
+                                               provider->identifier);
+
+       provider->signal_watch = g_dbus_add_signal_watch(connection,
+                                       CONNMAN_SERVICE, connmand_vpn_path,
+                                       CONNMAN_SERVICE_INTERFACE,
+                                       PROPERTY_CHANGED,
+                                       provider_property_changed,
+                                       provider, NULL);
+
+       g_free(connmand_vpn_path);
+
        return 0;
 }
 
@@ -1939,6 +2045,7 @@ static void provider_initialize(struct vpn_provider 
*provider)
        provider->domain = NULL;
        provider->identifier = NULL;
        provider->immutable = false;
+       provider->do_split_routing = false;
        provider->user_networks = NULL;
        provider->routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                                        NULL, free_route);
@@ -2110,6 +2217,7 @@ int __vpn_provider_create(DBusMessage *msg)
        GSList *networks = NULL;
        char *ident;
        int err;
+       dbus_bool_t split_routing = false;
 
        dbus_message_iter_init(msg, &iter);
        dbus_message_iter_recurse(&iter, &array);
@@ -2136,6 +2244,11 @@ int __vpn_provider_create(DBusMessage *msg)
                                        g_str_equal(key, "Domain"))
                                dbus_message_iter_get_basic(&value, &domain);
                        break;
+               case DBUS_TYPE_BOOLEAN:
+                       if (g_str_equal(key, "SplitRouting"))
+                               dbus_message_iter_get_basic(&value,
+                                                       &split_routing);
+                       break;
                case DBUS_TYPE_ARRAY:
                        if (g_str_equal(key, "UserRoutes"))
                                networks = get_user_networks(&value);
@@ -2169,6 +2282,7 @@ int __vpn_provider_create(DBusMessage *msg)
                provider->domain = g_strdup(domain);
                provider->name = g_strdup(name);
                provider->type = g_strdup(type);
+               provider->do_split_routing = split_routing;
 
                if (provider_register(provider) == 0)
                        vpn_provider_load(provider);
@@ -2489,6 +2603,10 @@ static int set_string(struct vpn_provider *provider,
                g_free(provider->domain);
                provider->domain = g_strdup(value);
                send_value(provider->path, "Domain", provider->domain);
+       } else if (g_str_equal(key, "SplitRouting")) {
+               connman_warn("VPN SplitRouting value attempted to set as "
+                                       "string, is boolean");
+               return -EINVAL;
        } else {
                struct vpn_setting *setting;
                bool replace = true;
@@ -2575,6 +2693,25 @@ const char *vpn_provider_get_string(struct vpn_provider 
*provider,
        return setting->value;
 }
 
+int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+                                               bool value, bool force_change)
+{
+       DBG("provider %p key %s", provider, key);
+
+       if (g_str_equal(key, "SplitRouting")) {
+               if (provider->do_split_routing == value && !force_change)
+                       return -EALREADY;
+
+               DBG("SplitRouting set to %s", bool2str(value));
+
+               provider->do_split_routing = value;
+               send_value_boolean(provider->path, key,
+                                       provider->do_split_routing);
+       }
+
+       return 0;
+}
+
 bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
                                                        bool default_value)
 {
-- 
2.20.1

------------------------------

Date: Tue,  8 Dec 2020 12:18:01 +0200
From: Jussi Laakkonen <jussi.laakko...@jolla.com>
Subject: [PATCH 15/15] doc: Document VPN connection SplitRouting
        boolean
To: connman@lists.01.org
Message-ID: <20201208101801.26715-16-jussi.laakko...@jolla.com>

---
 doc/vpn-connection-api.txt | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/doc/vpn-connection-api.txt b/doc/vpn-connection-api.txt
index ec557889..6e6293e4 100644
--- a/doc/vpn-connection-api.txt
+++ b/doc/vpn-connection-api.txt
@@ -130,7 +130,14 @@ Properties string State [readonly]
                        configured externally via a configuration file.
 
                        The only valid operation are Connect(), Disconnect()
-                        and GetProperties()
+                       and GetProperties()
+
+               boolean SplitRouting
+
+                       This value reflects the split routing setting on
+                       connmand side. By default, this value is omitted and
+                       defaults to false. The value needs to be explicitly
+                       set to true for VPN to be split routed.
 
                int Index [readonly]
 
-- 
2.20.1

------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list -- connman@lists.01.org
To unsubscribe send an email to connman-le...@lists.01.org


------------------------------

End of connman Digest, Vol 62, Issue 11
***************************************

Reply via email to