summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-11-12 14:07:30 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-11-23 12:58:51 +0200
commit4034f337edbb89f87465a05066cace379f6cc14f (patch)
treed1a7f223fd3866c46ddc7e857e8d8bdf58c2d435
parenta7113388cbe5a919d0b5c4866257fef6f2107d36 (diff)
downloadconnman-4034f337edbb89f87465a05066cace379f6cc14f.tar.gz
connman-4034f337edbb89f87465a05066cace379f6cc14f.tar.bz2
connman-4034f337edbb89f87465a05066cace379f6cc14f.zip
provider: Refactor server and user route handling
The server and user route handling is refactored in order to reflect the vpn dbus API changes. The routes are now array of dicts in dbus API.
-rw-r--r--include/provider.h10
-rw-r--r--plugins/vpn.c467
-rw-r--r--src/dbus.c17
-rw-r--r--src/provider.c42
-rw-r--r--vpn/vpn-provider.c633
5 files changed, 987 insertions, 182 deletions
diff --git a/include/provider.h b/include/provider.h
index b663f37e..548bd610 100644
--- a/include/provider.h
+++ b/include/provider.h
@@ -56,6 +56,13 @@ enum connman_provider_error {
CONNMAN_PROVIDER_ERROR_AUTH_FAILED = 3,
};
+enum connman_provider_route_type {
+ CONNMAN_PROVIDER_ROUTE_UNKNOWN = 0,
+ CONNMAN_PROVIDER_ROUTE_ALL = 0,
+ CONNMAN_PROVIDER_ROUTE_USER = 1,
+ CONNMAN_PROVIDER_ROUTE_SERVER = 2,
+};
+
struct connman_provider;
struct connman_ipaddress;
@@ -119,6 +126,9 @@ struct connman_provider_driver {
const char * (*get_property) (struct connman_provider *provider,
const char *key);
int (*create) (DBusMessage *msg);
+ int (*set_routes) (struct connman_provider *provider,
+ enum connman_provider_route_type type);
+ connman_bool_t (*check_routes) (struct connman_provider *provider);
};
int connman_provider_driver_register(struct connman_provider_driver *driver);
diff --git a/plugins/vpn.c b/plugins/vpn.c
index da1f982d..9aa8f1d7 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -39,6 +39,7 @@
#include <connman/provider.h>
#include <connman/ipaddress.h>
#include <connman/vpn-dbus.h>
+#include <connman/inet.h>
#define DBUS_TIMEOUT 10000
@@ -51,6 +52,13 @@ static guint added_watch;
static guint removed_watch;
static guint property_watch;
+struct vpn_route {
+ int family;
+ char *network;
+ char *netmask;
+ char *gateway;
+};
+
struct connection_data {
char *path;
struct connman_provider *provider;
@@ -64,6 +72,8 @@ struct connection_data {
char *domain;
char **nameservers;
+ GHashTable *server_routes;
+ GHashTable *user_routes;
GHashTable *setting_strings;
struct connman_ipaddress *ip;
@@ -197,6 +207,16 @@ out:
return err;
}
+static void destroy_route(gpointer user_data)
+{
+ struct vpn_route *route = user_data;
+
+ g_free(route->network);
+ g_free(route->netmask);
+ g_free(route->gateway);
+ g_free(route);
+}
+
static struct connection_data *create_connection_data(const char *path)
{
struct connection_data *data;
@@ -213,6 +233,11 @@ static struct connection_data *create_connection_data(const char *path)
data->setting_strings = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, g_free);
+ data->server_routes = g_hash_table_new_full(g_direct_hash,
+ g_str_equal, g_free, destroy_route);
+ data->user_routes = g_hash_table_new_full(g_str_hash,
+ g_str_equal, g_free, destroy_route);
+
return data;
}
@@ -792,24 +817,175 @@ static void set_dbus_ident(char *ident)
}
}
+static struct vpn_route *parse_user_route(const char *user_route)
+{
+ char *network, *netmask;
+ struct vpn_route *route = NULL;
+ int family = PF_UNSPEC;
+ char **elems = g_strsplit(user_route, "/", 0);
+
+ if (elems == NULL)
+ return NULL;
+
+ network = elems[0];
+ if (network == NULL || *network == '\0') {
+ DBG("no network/netmask set");
+ goto out;
+ }
+
+ netmask = elems[1];
+ if (netmask != NULL && *netmask == '\0') {
+ DBG("no netmask set");
+ goto out;
+ }
+
+ if (g_strrstr(network, ":") != NULL)
+ family = AF_INET6;
+ else if (g_strrstr(network, ".") != NULL) {
+ family = AF_INET;
+
+ if (g_strrstr(netmask, ".") == NULL) {
+ /* We have netmask length */
+ in_addr_t addr;
+ struct in_addr netmask_in;
+ unsigned char prefix_len = 32;
+
+ if (netmask != NULL) {
+ char *ptr;
+ long int value = strtol(netmask, &ptr, 10);
+ if (ptr != netmask && *ptr == '\0' &&
+ value <= 32)
+ prefix_len = value;
+ }
+
+ addr = 0xffffffff << (32 - prefix_len);
+ netmask_in.s_addr = htonl(addr);
+ netmask = inet_ntoa(netmask_in);
+
+ DBG("network %s netmask %s", network, netmask);
+ }
+ }
+
+ route = g_try_new(struct vpn_route, 1);
+ if (route == NULL)
+ goto out;
+
+ route->network = g_strdup(network);
+ route->netmask = g_strdup(netmask);
+ route->gateway = NULL;
+ route->family = family;
+
+out:
+ g_strfreev(elems);
+ return route;
+}
+
+static GSList *get_user_networks(DBusMessageIter *array)
+{
+ DBusMessageIter entry;
+ GSList *list = NULL;
+
+ dbus_message_iter_recurse(array, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+ const char *val;
+ struct vpn_route *route;
+
+ dbus_message_iter_get_basic(&entry, &val);
+
+ route = parse_user_route(val);
+ if (route != NULL)
+ list = g_slist_prepend(list, route);
+
+ dbus_message_iter_next(&entry);
+ }
+
+ return list;
+}
+
+static void append_route(DBusMessageIter *iter, void *user_data)
+{
+ struct vpn_route *route = user_data;
+ DBusMessageIter item;
+ int family = 0;
+
+ connman_dbus_dict_open(iter, &item);
+
+ if (route == NULL)
+ goto empty_dict;
+
+ if (route->family == AF_INET)
+ family = 4;
+ else if (route->family == AF_INET6)
+ family = 6;
+
+ if (family != 0)
+ connman_dbus_dict_append_basic(&item, "ProtocolFamily",
+ DBUS_TYPE_INT32, &family);
+
+ if (route->network != NULL)
+ connman_dbus_dict_append_basic(&item, "Network",
+ DBUS_TYPE_STRING, &route->network);
+
+ if (route->netmask != NULL)
+ connman_dbus_dict_append_basic(&item, "Netmask",
+ DBUS_TYPE_STRING, &route->netmask);
+
+ if (route->gateway != NULL)
+ connman_dbus_dict_append_basic(&item, "Gateway",
+ DBUS_TYPE_STRING, &route->gateway);
+
+empty_dict:
+ connman_dbus_dict_close(iter, &item);
+}
+
+static void append_routes(DBusMessageIter *iter, void *user_data)
+{
+ GSList *list, *routes = user_data;
+
+ DBG("routes %p", routes);
+
+ for (list = routes; list != NULL; list = g_slist_next(list)) {
+ DBusMessageIter dict;
+ struct vpn_route *route = list->data;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
+ &dict);
+ append_route(&dict, route);
+ dbus_message_iter_close_container(iter, &dict);
+ }
+}
+
static int create_configuration(DBusMessage *msg)
{
DBusMessage *new_msg;
DBusPendingCall *call;
- DBusMessageIter iter, array;
+ DBusMessageIter iter, array, new_iter, new_dict;
const char *type = NULL, *name = NULL;
const char *host = NULL, *domain = NULL;
- char *ident, *me;
- int err;
+ char *ident, *me = NULL;
+ int err = 0;
dbus_bool_t result;
struct connection_data *data;
+ GSList *networks = NULL;
+
+ /*
+ * We copy the old message data into new message. We cannot
+ * just use the old message as is because the user route
+ * information is not in the same format in vpnd.
+ */
+ new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
+ dbus_message_iter_init_append(new_msg, &new_iter);
+ connman_dbus_dict_open(&new_iter, &new_dict);
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry, value;
+ void *item_value;
const char *key;
+ int value_type;
dbus_message_iter_recurse(&array, &entry);
dbus_message_iter_get_basic(&entry, &key);
@@ -817,29 +993,58 @@ static int create_configuration(DBusMessage *msg)
dbus_message_iter_next(&entry);
dbus_message_iter_recurse(&entry, &value);
- switch (dbus_message_iter_get_arg_type(&value)) {
+ value_type = dbus_message_iter_get_arg_type(&value);
+ item_value = NULL;
+
+ switch (value_type) {
case DBUS_TYPE_STRING:
- if (g_str_equal(key, "Type") == TRUE)
- dbus_message_iter_get_basic(&value, &type);
- else if (g_str_equal(key, "Name") == TRUE)
- dbus_message_iter_get_basic(&value, &name);
- else if (g_str_equal(key, "Host") == TRUE)
- dbus_message_iter_get_basic(&value, &host);
- else if (g_str_equal(key, "VPN.Domain") == TRUE)
- dbus_message_iter_get_basic(&value, &domain);
+ dbus_message_iter_get_basic(&value, &item_value);
+
+ if (g_str_equal(key, "Type") == TRUE) {
+ type = (const char *)item_value;
+ } else if (g_str_equal(key, "Name") == TRUE) {
+ name = (const char *)item_value;
+ } else if (g_str_equal(key, "Host") == TRUE) {
+ host = (const char *)item_value;
+ } else if (g_str_equal(key, "VPN.Domain") == TRUE) {
+ domain = (const char *)item_value;
+ }
+
+ DBG("%s %s", key, (char *)item_value);
+
+ if (item_value != NULL)
+ connman_dbus_dict_append_basic(&new_dict, key,
+ value_type, &item_value);
+ break;
+ case DBUS_TYPE_ARRAY:
+ if (g_str_equal(key, "Networks") == TRUE) {
+ networks = get_user_networks(&value);
+ connman_dbus_dict_append_array(&new_dict,
+ "UserRoutes",
+ DBUS_TYPE_DICT_ENTRY,
+ append_routes,
+ networks);
+ }
break;
}
dbus_message_iter_next(&array);
}
- DBG("VPN type %s name %s host %s domain %s", type, name, host, domain);
+ connman_dbus_dict_close(&new_iter, &new_dict);
- if (host == NULL || domain == NULL)
- return -EINVAL;
+ DBG("VPN type %s name %s host %s domain %s networks %p",
+ type, name, host, domain, networks);
+
+ if (host == NULL || domain == NULL) {
+ err = -EINVAL;
+ goto done;
+ }
- if (type == NULL || name == NULL)
- return -EOPNOTSUPP;
+ if (type == NULL || name == NULL) {
+ err = -EOPNOTSUPP;
+ goto done;
+ }
ident = g_strdup_printf("%s_%s", host, domain);
set_dbus_ident(ident);
@@ -850,24 +1055,25 @@ static int create_configuration(DBusMessage *msg)
if (data != NULL) {
if (data->call != NULL) {
connman_error("Dbus call already pending");
- return -EINPROGRESS;
+ err = -EINPROGRESS;
+ goto done;
}
} else {
data = create_connection_data(ident);
- if (data == NULL)
- return -ENOMEM;
+ if (data == NULL) {
+ err = -ENOMEM;
+ goto done;
+ }
g_hash_table_insert(vpn_connections, g_strdup(ident), data);
}
/*
* User called net.connman.Manager.ConnectProvider if we are here.
- * The config dict is already there in the original message so use it.
+ * So use the data from original message in the new msg.
*/
me = g_strdup(dbus_message_get_destination(msg));
- new_msg = dbus_message_copy(msg);
-
dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
dbus_message_set_path(new_msg, "/");
dbus_message_set_destination(new_msg, VPN_SERVICE);
@@ -888,10 +1094,83 @@ static int create_configuration(DBusMessage *msg)
done:
dbus_message_unref(new_msg);
+ if (networks != NULL)
+ g_slist_free_full(networks, destroy_route);
+
+
g_free(me);
return err;
}
+static void set_route(struct connection_data *data, struct vpn_route *route)
+{
+ if (route->family == AF_INET6) {
+ unsigned char prefix_len = atoi(route->netmask);
+
+ connman_inet_add_ipv6_network_route(data->index,
+ route->network,
+ route->gateway,
+ prefix_len);
+ } else {
+ connman_inet_add_network_route(data->index, route->network,
+ route->gateway,
+ route->netmask);
+ }
+}
+
+static int set_routes(struct connman_provider *provider,
+ enum connman_provider_route_type type)
+{
+ struct connection_data *data;
+ GHashTableIter iter;
+ gpointer value, key;
+
+ DBG("provider %p", provider);
+
+ data = connman_provider_get_data(provider);
+ if (data == NULL)
+ return -EINVAL;
+
+ if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
+ type == CONNMAN_PROVIDER_ROUTE_USER) {
+ g_hash_table_iter_init(&iter, data->user_routes);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
+ set_route(data, value);
+ }
+
+ if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
+ type == CONNMAN_PROVIDER_ROUTE_SERVER) {
+ g_hash_table_iter_init(&iter, data->server_routes);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
+ set_route(data, value);
+ }
+
+ return 0;
+}
+
+static connman_bool_t check_routes(struct connman_provider *provider)
+{
+ struct connection_data *data;
+
+ DBG("provider %p", provider);
+
+ data = connman_provider_get_data(provider);
+ if (data == NULL)
+ return FALSE;
+
+ if (data->user_routes != NULL &&
+ g_hash_table_size(data->user_routes) > 0)
+ return TRUE;
+
+ if (data->server_routes != NULL &&
+ g_hash_table_size(data->server_routes) > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
static struct connman_provider_driver provider_driver = {
.name = "VPN",
.type = CONNMAN_PROVIDER_TYPE_VPN,
@@ -902,6 +1181,8 @@ static struct connman_provider_driver provider_driver = {
.set_property = set_string,
.get_property = get_string,
.create = create_configuration,
+ .set_routes = set_routes,
+ .check_routes = check_routes,
};
static void destroy_provider(struct connection_data *data)
@@ -935,6 +1216,8 @@ static void connection_destroy(gpointer hash_data)
g_free(data->name);
g_free(data->host);
g_free(data->domain);
+ g_hash_table_destroy(data->server_routes);
+ g_hash_table_destroy(data->user_routes);
g_strfreev(data->nameservers);
g_hash_table_destroy(data->setting_strings);
connman_ipaddress_free(data->ip);
@@ -1024,6 +1307,127 @@ static gboolean connection_added(DBusConnection *conn, DBusMessage *message,
return TRUE;
}
+static int save_route(GHashTable *routes, int family, const char *network,
+ const char *netmask, const char *gateway)
+{
+ struct vpn_route *route;
+ char *key = g_strdup_printf("%d/%s/%s", family, network, netmask);
+
+ DBG("family %d network %s netmask %s", family, network, netmask);
+
+ route = g_hash_table_lookup(routes, key);
+ if (route == NULL) {
+ route = g_try_new0(struct vpn_route, 1);
+ if (route == NULL) {
+ connman_error("out of memory");
+ return -ENOMEM;
+ }
+
+ route->family = family;
+ route->network = g_strdup(network);
+ route->netmask = g_strdup(netmask);
+ route->gateway = g_strdup(gateway);
+
+ g_hash_table_replace(routes, key, route);
+ } else
+ g_free(key);
+
+ return 0;
+}
+
+static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
+{
+ DBusMessageIter dict;
+ const char *network, *netmask, *gateway;
+ int family;
+
+ dbus_message_iter_recurse(dicts, &dict);
+
+ network = netmask = gateway = NULL;
+ family = PF_UNSPEC;
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+
+ DBusMessageIter entry, value;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ if (g_str_equal(key, "ProtocolFamily") == TRUE) {
+ int pf;
+ dbus_message_iter_get_basic(&value, &pf);
+ switch (pf) {
+ case 4:
+ family = AF_INET;
+ break;
+ case 6:
+ family = AF_INET6;
+ break;
+ }
+ DBG("family %d", family);
+ } else if (g_str_equal(key, "Netmask") == TRUE) {
+ dbus_message_iter_get_basic(&value, &netmask);
+ DBG("netmask %s", netmask);
+ } else if (g_str_equal(key, "Network") == TRUE) {
+ dbus_message_iter_get_basic(&value, &network);
+ DBG("host %s", network);
+ } else if (g_str_equal(key, "Gateway") == TRUE) {
+ dbus_message_iter_get_basic(&value, &gateway);
+ DBG("gateway %s", gateway);
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ if (netmask == NULL || network == NULL || gateway == NULL) {
+ DBG("Value missing.");
+ return -EINVAL;
+ }
+
+ return save_route(routes, family, network, netmask, gateway);
+}
+
+static int routes_changed(DBusMessageIter *array, GHashTable *routes)
+{
+ DBusMessageIter entry;
+ int ret = -EINVAL;
+
+ if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
+ DBG("Expecting array, ignoring routes.");
+ return -EINVAL;
+ }
+
+ while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
+
+ dbus_message_iter_recurse(array, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) ==
+ DBUS_TYPE_STRUCT) {
+ DBusMessageIter dicts;
+
+ dbus_message_iter_recurse(&entry, &dicts);
+
+ while (dbus_message_iter_get_arg_type(&dicts) ==
+ DBUS_TYPE_ARRAY) {
+ int err = read_route_dict(routes, &dicts);
+ if (ret != 0)
+ ret = err;
+ dbus_message_iter_next(&dicts);
+ }
+
+ dbus_message_iter_next(&entry);
+ }
+
+ dbus_message_iter_next(array);
+ }
+
+ return ret;
+}
+
static gboolean property_changed(DBusConnection *conn,
DBusMessage *message,
void *user_data)
@@ -1081,9 +1485,22 @@ static gboolean property_changed(DBusConnection *conn,
err = extract_ip(&value, AF_INET6, data);
ip_set = TRUE;
} else if (g_str_equal(key, "ServerRoutes") == TRUE) {
- /* XXX: TBD */
+ err = routes_changed(&value, data->server_routes);
+ /*
+ * Note that the vpnd will delay the route sending a bit
+ * (in order to collect the routes from VPN client),
+ * so we might have got the State changed property before
+ * we got ServerRoutes. This means that we must try to set
+ * the routes here because they would be left unset otherwise.
+ */
+ if (err == 0)
+ set_routes(data->provider,
+ CONNMAN_PROVIDER_ROUTE_SERVER);
} else if (g_str_equal(key, "UserRoutes") == TRUE) {
- /* XXX: TBD */
+ err = routes_changed(&value, data->user_routes);
+ if (err == 0)
+ set_routes(data->provider,
+ CONNMAN_PROVIDER_ROUTE_USER);
} else if (g_str_equal(key, "Nameservers") == TRUE) {
extract_nameservers(&value, data);
}
diff --git a/src/dbus.c b/src/dbus.c
index 38a6b92f..9d19f946 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -189,6 +189,23 @@ void connman_dbus_property_append_array(DBusMessageIter *iter,
variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING;
array_sig = DBUS_TYPE_OBJECT_PATH_AS_STRING;
break;
+ case DBUS_TYPE_DICT_ENTRY:
+ variant_sig = DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+ array_sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+ break;
default:
return;
}
diff --git a/src/provider.c b/src/provider.c
index 64a871b5..cd11db97 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -38,25 +38,14 @@ static GHashTable *provider_hash = NULL;
static GSList *driver_list = NULL;
-struct connman_route {
- int family;
- char *host;
- char *netmask;
- char *gateway;
-};
-
struct connman_provider {
int refcount;
struct connman_service *vpn_service;
int index;
char *identifier;
int family;
- GHashTable *routes;
struct connman_provider_driver *driver;
void *driver_data;
- GHashTable *user_routes;
- gchar **user_networks;
- gsize num_user_networks;
};
void __connman_provider_append_properties(struct connman_provider *provider,
@@ -109,9 +98,6 @@ static void provider_destruct(struct connman_provider *provider)
DBG("provider %p", provider);
g_free(provider->identifier);
- g_strfreev(provider->user_networks);
- g_hash_table_destroy(provider->routes);
- g_hash_table_destroy(provider->user_routes);
g_free(provider);
}
@@ -248,6 +234,10 @@ static int set_connected(struct connman_provider *provider,
provider_indicate_state(provider,
CONNMAN_SERVICE_STATE_READY);
+ if (provider->driver != NULL && provider->driver->set_routes)
+ provider->driver->set_routes(provider,
+ CONNMAN_PROVIDER_ROUTE_ALL);
+
} else {
if (ipconfig != NULL) {
provider_indicate_state(provider,
@@ -396,13 +386,8 @@ __connman_provider_check_routes(struct connman_provider *provider)
if (provider == NULL)
return FALSE;
- if (provider->user_routes != NULL &&
- g_hash_table_size(provider->user_routes) > 0)
- return TRUE;
-
- if (provider->routes != NULL &&
- g_hash_table_size(provider->routes) > 0)
- return TRUE;
+ if (provider->driver != NULL && provider->driver->check_routes)
+ return provider->driver->check_routes(provider);
return FALSE;
}
@@ -601,27 +586,12 @@ static void provider_offline_mode(connman_bool_t enabled)
}
-static void destroy_route(gpointer user_data)
-{
- struct connman_route *route = user_data;
-
- g_free(route->host);
- g_free(route->netmask);
- g_free(route->gateway);
- g_free(route);
-}
-
static void provider_initialize(struct connman_provider *provider)
{
DBG("provider %p", provider);
provider->index = 0;
provider->identifier = NULL;
- provider->user_networks = NULL;
- provider->routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, destroy_route);
- provider->user_routes = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, destroy_route);
}
static struct connman_provider *provider_new(void)
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index 462dc26c..eb12f04e 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -30,12 +30,18 @@
#include <gdbus.h>
#include <connman/log.h>
#include <gweb/gresolv.h>
+#include <netdb.h>
#include "../src/connman.h"
#include "connman/vpn-dbus.h"
#include "vpn-provider.h"
#include "vpn.h"
+enum {
+ USER_ROUTES_CHANGED = 0x01,
+ SERVER_ROUTES_CHANGED = 0x02,
+};
+
static DBusConnection *connection;
static GHashTable *provider_hash;
static GSList *driver_list;
@@ -43,7 +49,7 @@ static int configuration_count;
struct vpn_route {
int family;
- char *host;
+ char *network;
char *netmask;
char *gateway;
};
@@ -65,34 +71,362 @@ struct vpn_provider {
void *driver_data;
GHashTable *setting_strings;
GHashTable *user_routes;
- gchar **user_networks;
- gsize num_user_networks;
+ GSList *user_networks;
GResolv *resolv;
char **host_ip;
DBusMessage *pending_msg;
struct vpn_ipconfig *ipconfig_ipv4;
struct vpn_ipconfig *ipconfig_ipv6;
char **nameservers;
+ int what_changed;
+ guint notify_id;
};
+static void free_route(gpointer data)
+{
+ struct vpn_route *route = data;
+
+ g_free(route->network);
+ g_free(route->netmask);
+ g_free(route->gateway);
+
+ g_free(route);
+}
+
+static void append_route(DBusMessageIter *iter, void *user_data)
+{
+ struct vpn_route *route = user_data;
+ DBusMessageIter item;
+ int family = 0;
+
+ connman_dbus_dict_open(iter, &item);
+
+ if (route == NULL)
+ goto empty_dict;
+
+ if (route->family == AF_INET)
+ family = 4;
+ else if (route->family == AF_INET6)
+ family = 6;
+
+ if (family != 0)
+ connman_dbus_dict_append_basic(&item, "ProtocolFamily",
+ DBUS_TYPE_INT32, &family);
+
+ if (route->network != NULL)
+ connman_dbus_dict_append_basic(&item, "Network",
+ DBUS_TYPE_STRING, &route->network);
+
+ if (route->netmask != NULL)
+ connman_dbus_dict_append_basic(&item, "Netmask",
+ DBUS_TYPE_STRING, &route->netmask);
+
+ if (route->gateway != NULL)
+ connman_dbus_dict_append_basic(&item, "Gateway",
+ DBUS_TYPE_STRING, &route->gateway);
+
+empty_dict:
+ connman_dbus_dict_close(iter, &item);
+}
+
+static void append_routes(DBusMessageIter *iter, void *user_data)
+{
+ GHashTable *routes = user_data;
+ GHashTableIter hash;
+ gpointer value, key;
+
+ if (routes == NULL) {
+ append_route(iter, NULL);
+ return;
+ }
+
+ g_hash_table_iter_init(&hash, routes);
+
+ while (g_hash_table_iter_next(&hash, &key, &value) == TRUE) {
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
+ &dict);
+ append_route(&dict, value);
+ dbus_message_iter_close_container(iter, &dict);
+ }
+}
+
+static void send_routes(struct vpn_provider *provider, GHashTable *routes,
+ const char *name)
+{
+ connman_dbus_property_changed_array(provider->path,
+ VPN_CONNECTION_INTERFACE,
+ name,
+ DBUS_TYPE_DICT_ENTRY,
+ append_routes,
+ routes);
+}
+
+static int provider_property_changed(struct vpn_provider *provider,
+ const char *name)
+{
+ DBG("provider %p name %s", provider, name);
+
+ if (g_str_equal(name, "UserRoutes") == TRUE)
+ send_routes(provider, provider->user_routes, name);
+ else if (g_str_equal(name, "ServerRoutes") == TRUE)
+ send_routes(provider, provider->routes, name);
+
+ return 0;
+}
+
+static GSList *read_route_dict(GSList *routes, DBusMessageIter *dicts)
+{
+ DBusMessageIter dict, value, entry;
+ const char *network, *netmask, *gateway;
+ struct vpn_route *route;
+ int family, type;
+ const char *key;
+
+ dbus_message_iter_recurse(dicts, &entry);
+
+ network = netmask = gateway = NULL;
+ family = PF_UNSPEC;
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_DICT_ENTRY) {
+
+ dbus_message_iter_recurse(&entry, &dict);
+ dbus_message_iter_get_basic(&dict, &key);
+
+ dbus_message_iter_next(&dict);
+ dbus_message_iter_recurse(&dict, &value);
+
+ type = dbus_message_iter_get_arg_type(&value);
+
+ switch (type) {
+ case DBUS_TYPE_STRING:
+ if (g_str_equal(key, "ProtocolFamily") == TRUE)
+ dbus_message_iter_get_basic(&value, &family);
+ else if (g_str_equal(key, "Network") == TRUE)
+ dbus_message_iter_get_basic(&value, &network);
+ else if (g_str_equal(key, "Netmask") == TRUE)
+ dbus_message_iter_get_basic(&value, &netmask);
+ else if (g_str_equal(key, "Gateway") == TRUE)
+ dbus_message_iter_get_basic(&value, &gateway);
+ break;
+ }
+
+ dbus_message_iter_next(&entry);
+ }
+
+ DBG("family %d network %s netmask %s gateway %s", family,
+ network, netmask, gateway);
+
+ if (network == NULL || netmask == NULL) {
+ DBG("Ignoring route as network/netmask is missing");
+ return routes;
+ }
+
+ route = g_try_new(struct vpn_route, 1);
+ if (route == NULL) {
+ g_slist_free_full(routes, free_route);
+ return NULL;
+ }
+
+ if (family == PF_UNSPEC) {
+ family = connman_inet_check_ipaddress(network);
+ if (family < 0) {
+ DBG("Cannot get address family of %s (%d/%s)", network,
+ family, gai_strerror(family));
+ if (strstr(network, ":") != NULL) {
+ DBG("Guessing it is IPv6");
+ family = AF_INET6;
+ } else {
+ DBG("Guessing it is IPv4");
+ family = AF_INET;
+ }
+ }
+ } else {
+ switch (family) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ default:
+ family = PF_UNSPEC;
+ break;
+ }
+ }
+
+ route->family = family;
+ route->network = g_strdup(network);
+ route->netmask = g_strdup(netmask);
+ route->gateway = g_strdup(gateway);
+
+ routes = g_slist_prepend(routes, route);
+ return routes;
+}
+
+static GSList *get_user_networks(DBusMessageIter *array)
+{
+ DBusMessageIter entry;
+ GSList *list = NULL;
+
+ while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
+
+ dbus_message_iter_recurse(array, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) ==
+ DBUS_TYPE_STRUCT) {
+ DBusMessageIter dicts;
+
+ dbus_message_iter_recurse(&entry, &dicts);
+
+ while (dbus_message_iter_get_arg_type(&dicts) ==
+ DBUS_TYPE_ARRAY) {
+
+ list = read_route_dict(list, &dicts);
+ dbus_message_iter_next(&dicts);
+ }
+
+ dbus_message_iter_next(&entry);
+ }
+
+ dbus_message_iter_next(array);
+ }
+
+ return list;
+}
+
+static void set_user_networks(struct vpn_provider *provider, GSList *networks)
+{
+ GSList *list;
+
+ for (list = networks; list != NULL; list = g_slist_next(list)) {
+ struct vpn_route *route= list->data;
+
+ if (__vpn_provider_append_user_route(provider,
+ route->family, route->network,
+ route->netmask) != 0)
+ break;
+ }
+}
+
+static void del_routes(struct vpn_provider *provider)
+{
+ GHashTableIter hash;
+ gpointer value, key;
+
+ g_hash_table_iter_init(&hash, provider->user_routes);
+ while (g_hash_table_iter_next(&hash, &key, &value) == TRUE) {
+ 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;
+}
+
+static gboolean provider_send_changed(gpointer data)
+{
+ struct vpn_provider *provider = data;
+
+ if (provider->what_changed & USER_ROUTES_CHANGED)
+ provider_property_changed(provider, "UserRoutes");
+
+ if (provider->what_changed & SERVER_ROUTES_CHANGED)
+ provider_property_changed(provider, "ServerRoutes");
+
+ provider->what_changed = 0;
+ provider->notify_id = 0;
+
+ return FALSE;
+}
+
+static void provider_schedule_changed(struct vpn_provider *provider, int flag)
+{
+ if (provider->notify_id != 0)
+ g_source_remove(provider->notify_id);
+
+ provider->what_changed |= flag;
+
+ provider->notify_id = g_timeout_add(100, provider_send_changed,
+ provider);
+}
+
static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+ struct vpn_provider *provider = data;
+ DBusMessageIter iter, value;
+ const char *name;
+ int type;
+
DBG("conn %p", conn);
- // XXX:
+ if (dbus_message_iter_init(msg, &iter) == FALSE)
+ return __connman_error_invalid_arguments(msg);
- return NULL;
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&iter, &value);
+
+ type = dbus_message_iter_get_arg_type(&value);
+
+ if (g_str_equal(name, "UserRoutes") == TRUE) {
+ GSList *networks;
+
+ if (type != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ networks = get_user_networks(&value);
+ if (networks != NULL) {
+ del_routes(provider);
+ provider->user_networks = networks;
+ set_user_networks(provider, provider->user_networks);
+
+ provider_schedule_changed(provider, USER_ROUTES_CHANGED);
+ provider_property_changed(provider, name);
+ }
+ } else
+ return __connman_error_invalid_property(msg);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static DBusMessage *clear_property(DBusConnection *conn, DBusMessage *msg,
void *data)
{
+ struct vpn_provider *provider = data;
+ const char *name;
+
DBG("conn %p", conn);
- // XXX:
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID);
- return NULL;
+ if (g_str_equal(name, "UserRoutes") == TRUE) {
+ del_routes(provider);
+
+ provider_property_changed(provider, name);
+ } else {
+ return __connman_error_invalid_property(msg);
+ }
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static DBusMessage *do_connect(DBusConnection *conn, DBusMessage *msg,
@@ -221,7 +555,7 @@ int __vpn_provider_append_user_route(struct vpn_provider *provider,
}
route->family = family;
- route->host = g_strdup(network);
+ route->network = g_strdup(network);
route->netmask = g_strdup(netmask);
g_hash_table_replace(provider->user_routes, key, route);
@@ -231,64 +565,103 @@ int __vpn_provider_append_user_route(struct vpn_provider *provider,
return 0;
}
-static void set_user_networks(struct vpn_provider *provider,
- char **networks)
+static struct vpn_route *get_route(char *route_str)
{
- int i = 0;
+ char **elems = g_strsplit(route_str, "/", 0);
+ char *network, *netmask, *gateway, *family_str;
+ int family = PF_UNSPEC;
+ struct vpn_route *route = NULL;
- while (networks[i] != NULL) {
- char **elems = g_strsplit(networks[i], "/", 0);
- char *network, *netmask;
- int family = PF_UNSPEC, ret;
+ if (elems == NULL)
+ return NULL;
- if (elems == NULL)
- break;
+ family_str = elems[0];
- network = elems[0];
- if (network == NULL || *network == '\0') {
- DBG("no network/netmask set");
- g_strfreev(elems);
- break;
- }
+ network = elems[1];
+ if (network == NULL || network[0] == '\0')
+ goto out;
+
+ netmask = elems[2];
+ if (netmask == NULL || netmask[0] == '\0')
+ goto out;
+
+ gateway = elems[3];
+
+ route = g_try_new0(struct vpn_route, 1);
+ if (route == NULL)
+ goto out;
- netmask = elems[1];
- if (netmask != NULL && *netmask == '\0') {
- DBG("no netmask set");
- g_strfreev(elems);
+ if (family_str[0] == '\0' || atoi(family_str) == 0) {
+ family = PF_UNSPEC;
+ } else {
+ switch (family_str[0]) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
break;
}
+ }
- if (g_strrstr(network, ":") != NULL)
- family = AF_INET6;
- else if (g_strrstr(network, ".") != NULL) {
- family = AF_INET;
+ if (g_strrstr(network, ":") != NULL) {
+ if (family != PF_UNSPEC && family != AF_INET6)
+ DBG("You have IPv6 address but you have non IPv6 route");
+ } else if (g_strrstr(network, ".") != NULL) {
+ if (family != PF_UNSPEC && family != AF_INET)
+ DBG("You have IPv4 address but you have non IPv4 route");
+
+ if (g_strrstr(netmask, ".") == NULL) {
+ /* We have netmask length */
+ in_addr_t addr;
+ struct in_addr netmask_in;
+ unsigned char prefix_len = 32;
+
+ if (netmask != NULL) {
+ char *ptr;
+ long int value = strtol(netmask, &ptr, 10);
+ if (ptr != netmask && *ptr == '\0' &&
+ value <= 32)
+ prefix_len = value;
+ }
- if (g_strrstr(netmask, ".") == NULL) {
- /* We have netmask length */
- in_addr_t addr;
- struct in_addr netmask_in;
- unsigned char prefix_len = 32;
+ addr = 0xffffffff << (32 - prefix_len);
+ netmask_in.s_addr = htonl(addr);
+ netmask = inet_ntoa(netmask_in);
- if (netmask != NULL)
- prefix_len = atoi(netmask);
+ DBG("network %s netmask %s", network, netmask);
+ }
+ }
- addr = 0xffffffff << (32 - prefix_len);
- netmask_in.s_addr = htonl(addr);
- netmask = inet_ntoa(netmask_in);
+ if (family == PF_UNSPEC) {
+ family = connman_inet_check_ipaddress(network);
+ if (family < 0 || family == PF_UNSPEC)
+ goto out;
+ }
- DBG("network %s netmask %s", network, netmask);
- }
- }
+ route->family = family;
+ route->network = g_strdup(network);
+ route->netmask = g_strdup(netmask);
+ route->gateway = g_strdup(gateway);
- ret = __vpn_provider_append_user_route(provider,
- family, network, netmask);
- g_strfreev(elems);
+out:
+ g_strfreev(elems);
+ return route;
+}
- if (ret != 0)
- break;
+static GSList *get_routes(gchar **networks)
+{
+ struct vpn_route *route;
+ GSList *routes = NULL;
+ int i;
- i++;
+ for (i = 0; networks[i] != NULL; i++) {
+ route = get_route(networks[i]);
+ if (route != NULL)
+ routes = g_slist_prepend(routes, route);
}
+
+ return routes;
}
static int provider_load_from_keyfile(struct vpn_provider *provider,
@@ -297,7 +670,8 @@ static int provider_load_from_keyfile(struct vpn_provider *provider,
gsize idx = 0;
gchar **settings;
gchar *key, *value;
- gsize length;
+ gsize length, num_user_networks;
+ gchar **networks = NULL;
settings = g_key_file_get_keys(keyfile, provider->identifier, &length,
NULL);
@@ -310,13 +684,13 @@ static int provider_load_from_keyfile(struct vpn_provider *provider,
key = settings[idx];
if (key != NULL) {
if (g_str_equal(key, "Networks") == TRUE) {
- g_strfreev(provider->user_networks);
- provider->user_networks =
- g_key_file_get_string_list(keyfile,
+ networks = g_key_file_get_string_list(keyfile,
provider->identifier,
key,
- &provider->num_user_networks,
+ &num_user_networks,
NULL);
+ provider->user_networks = get_routes(networks);
+
} else {
value = g_key_file_get_string(keyfile,
provider->identifier,
@@ -329,6 +703,7 @@ static int provider_load_from_keyfile(struct vpn_provider *provider,
idx += 1;
}
g_strfreev(settings);
+ g_strfreev(networks);
if (provider->user_networks != NULL)
set_user_networks(provider, provider->user_networks);
@@ -353,6 +728,49 @@ static int vpn_provider_load(struct vpn_provider *provider)
return 0;
}
+static gchar **create_network_list(GSList *networks, gsize *count)
+{
+ GSList *list;
+ gchar **result = NULL;
+ unsigned int num_elems = 0;
+
+ for (list = networks; list != NULL; list = g_slist_next(list)) {
+ struct vpn_route *route = list->data;
+ int family;
+
+ result = g_try_realloc(result,
+ (num_elems + 1) * sizeof(gchar *));
+ if (result == NULL)
+ return NULL;
+
+ switch (route->family) {
+ case AF_INET:
+ family = 4;
+ break;
+ case AF_INET6:
+ family = 6;
+ break;
+ default:
+ family = 0;
+ break;
+ }
+
+ result[num_elems] = g_strdup_printf("%d/%s/%s/%s",
+ family, route->network, route->netmask,
+ route->gateway == NULL ? "" : route->gateway);
+
+ num_elems++;
+ }
+
+ result = g_try_realloc(result, (num_elems + 1) * sizeof(gchar *));
+ if (result == NULL)
+ return NULL;
+
+ result[num_elems] = NULL;
+ *count = num_elems;
+ return result;
+}
+
static int vpn_provider_save(struct vpn_provider *provider)
{
GKeyFile *keyfile;
@@ -371,11 +789,21 @@ 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 != NULL)
- g_key_file_set_string_list(keyfile, provider->identifier,
- "Networks",
- (const gchar **)provider->user_networks,
- provider->num_user_networks);
+ if (provider->user_networks != NULL) {
+ gchar **networks;
+ gsize network_count;
+
+ networks = create_network_list(provider->user_networks,
+ &network_count);
+ if (networks != NULL) {
+ g_key_file_set_string_list(keyfile,
+ provider->identifier,
+ "Networks",
+ (const gchar ** const)networks,
+ network_count);
+ g_strfreev(networks);
+ }
+ }
if (provider->driver != NULL && provider->driver->save != NULL)
provider->driver->save(provider, keyfile);
@@ -467,13 +895,16 @@ static void provider_destruct(struct vpn_provider *provider)
{
DBG("provider %p", provider);
+ if (provider->notify_id != 0)
+ g_source_remove(provider->notify_id);
+
g_free(provider->name);
g_free(provider->type);
g_free(provider->host);
g_free(provider->domain);
g_free(provider->identifier);
g_free(provider->path);
- g_strfreev(provider->user_networks);
+ g_slist_free_full(provider->user_networks, free_route);
g_strfreev(provider->nameservers);
g_hash_table_destroy(provider->routes);
g_hash_table_destroy(provider->user_routes);
@@ -777,6 +1208,14 @@ static void append_properties(DBusMessageIter *iter,
connman_dbus_dict_append_array(&dict, "Nameservers",
DBUS_TYPE_STRING, append_dns, provider);
+ connman_dbus_dict_append_array(&dict, "UserRoutes",
+ DBUS_TYPE_DICT_ENTRY, append_routes,
+ provider->user_routes);
+
+ connman_dbus_dict_append_array(&dict, "ServerRoutes",
+ DBUS_TYPE_DICT_ENTRY, append_routes,
+ provider->routes);
+
connman_dbus_dict_close(iter, &dict);
}
@@ -807,20 +1246,20 @@ static void provider_append_routes(gpointer key, gpointer value,
* VPN server, then we must discard that because the
* server cannot be contacted via VPN tunnel.
*/
- if (check_host(provider->host_ip, route->host) == TRUE) {
+ if (check_host(provider->host_ip, route->network) == TRUE) {
DBG("Discarding VPN route to %s via %s at index %d",
- route->host, route->gateway, index);
+ 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->host,
+ connman_inet_add_ipv6_network_route(index, route->network,
route->gateway,
prefix_len);
} else {
- connman_inet_add_network_route(index, route->host,
+ connman_inet_add_network_route(index, route->network,
route->gateway,
route->netmask);
}
@@ -915,16 +1354,6 @@ static void unregister_provider(gpointer data)
vpn_provider_unref(provider);
}
-static void destroy_route(gpointer user_data)
-{
- struct vpn_route *route = user_data;
-
- g_free(route->host);
- g_free(route->netmask);
- g_free(route->gateway);
- g_free(route);
-}
-
static void provider_initialize(struct vpn_provider *provider)
{
DBG("provider %p", provider);
@@ -937,9 +1366,9 @@ static void provider_initialize(struct vpn_provider *provider)
provider->identifier = NULL;
provider->user_networks = NULL;
provider->routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, destroy_route);
+ NULL, free_route);
provider->user_routes = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, destroy_route);
+ g_free, free_route);
provider->setting_strings = g_hash_table_new_full(g_str_hash,
g_str_equal, g_free, g_free);
}
@@ -1102,52 +1531,15 @@ static void provider_create_all_from_type(const char *provider_type)
g_strfreev(providers);
}
-static char **get_user_networks(DBusMessageIter *array, int *count)
-{
- DBusMessageIter entry;
- char **networks = NULL;
- GSList *list = NULL, *l;
- int len;
-
- dbus_message_iter_recurse(array, &entry);
-
- while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
- const char *val;
- dbus_message_iter_get_basic(&entry, &val);
-
- list = g_slist_prepend(list, g_strdup(val));
- dbus_message_iter_next(&entry);
- }
-
- len = g_slist_length(list);
- if (len == 0)
- goto out;
-
- networks = g_try_new(char *, len + 1);
- if (networks == NULL)
- goto out;
-
- *count = len;
- networks[len] = 0;
-
- for (l = list; l != NULL; l = g_slist_next(l))
- networks[--len] = l->data;
-
-out:
- g_slist_free(list);
-
- return networks;
-}
-
int __vpn_provider_create_and_connect(DBusMessage *msg)
{
struct vpn_provider *provider;
DBusMessageIter iter, array;
const char *type = NULL, *name = NULL;
const char *host = NULL, *domain = NULL;
- char **networks = NULL;
+ GSList *networks = NULL;
char *ident;
- int err, count = 0;
+ int err;
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
@@ -1174,8 +1566,8 @@ int __vpn_provider_create_and_connect(DBusMessage *msg)
dbus_message_iter_get_basic(&value, &domain);
break;
case DBUS_TYPE_ARRAY:
- if (g_str_equal(key, "Networks") == TRUE)
- networks = get_user_networks(&value, &count);
+ if (g_str_equal(key, "UserRoutes") == TRUE)
+ networks = get_user_networks(&value);
break;
}
@@ -1216,9 +1608,8 @@ int __vpn_provider_create_and_connect(DBusMessage *msg)
}
if (networks != NULL) {
- g_strfreev(provider->user_networks);
+ g_slist_free_full(provider->user_networks, free_route);
provider->user_networks = networks;
- provider->num_user_networks = count;
set_user_networks(provider, provider->user_networks);
}
@@ -1600,7 +1991,7 @@ int vpn_provider_append_route(struct vpn_provider *provider,
route->netmask = g_strdup(value);
break;
case PROVIDER_ROUTE_TYPE_ADDR:
- route->host = g_strdup(value);
+ route->network = g_strdup(value);
break;
case PROVIDER_ROUTE_TYPE_GW:
route->gateway = g_strdup(value);