*
* Connection Manager
*
- * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include <config.h>
#endif
-#include <errno.h>
-#include <unistd.h>
#include <string.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
#include <net/if.h>
-#include <net/route.h>
#include <gdbus.h>
struct gateway_data {
int index;
- char *gateway;
- struct connman_element *element;
+ struct connman_service *service;
+ char *ipv4_gateway;
+ char *ipv6_gateway;
unsigned int order;
gboolean active;
+ /* VPN extra data */
+ gboolean vpn;
+ char *vpn_ip;
+ int vpn_phy_index;
};
-static GSList *gateway_list = NULL;
+static GHashTable *gateway_hash = NULL;
static struct gateway_data *find_gateway(int index, const char *gateway)
{
- GSList *list;
+ GHashTableIter iter;
+ gpointer value, key;
if (gateway == NULL)
return NULL;
- for (list = gateway_list; list; list = list->next) {
- struct gateway_data *data = list->data;
+ g_hash_table_iter_init(&iter, gateway_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct gateway_data *data = value;
- if (data->gateway == NULL)
+ if (data->ipv4_gateway == NULL)
continue;
if (data->index == index &&
- g_str_equal(data->gateway, gateway) == TRUE)
+ g_str_equal(data->ipv4_gateway, gateway)
+ == TRUE)
return data;
}
return NULL;
}
-static int set_route(struct connman_element *element, const char *gateway)
-{
- struct ifreq ifr;
- struct rtentry rt;
- struct sockaddr_in addr;
- int sk, err;
-
- DBG("element %p", element);
-
- sk = socket(PF_INET, SOCK_DGRAM, 0);
- if (sk < 0)
- return -1;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = element->index;
-
- if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
- close(sk);
- return -1;
- }
-
- DBG("ifname %s", ifr.ifr_name);
-
- memset(&rt, 0, sizeof(rt));
- rt.rt_flags = RTF_UP | RTF_HOST;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(gateway);
- memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
-
- rt.rt_dev = ifr.ifr_name;
-
- err = ioctl(sk, SIOCADDRT, &rt);
- if (err < 0)
- connman_error("Setting host gateway route failed (%s)",
- strerror(errno));
-
- memset(&rt, 0, sizeof(rt));
- rt.rt_flags = RTF_UP | RTF_GATEWAY;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(gateway);
- memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
-
- err = ioctl(sk, SIOCADDRT, &rt);
- if (err < 0)
- connman_error("Setting default route failed (%s)",
- strerror(errno));
-
- close(sk);
-
- return err;
-}
-
-static int del_route(struct connman_element *element, const char *gateway)
+static int del_routes(struct gateway_data *data)
{
- struct ifreq ifr;
- struct rtentry rt;
- struct sockaddr_in addr;
- int sk, err;
-
- DBG("element %p", element);
-
- sk = socket(PF_INET, SOCK_DGRAM, 0);
- if (sk < 0)
- return -1;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = element->index;
-
- if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
- close(sk);
- return -1;
+ if (data->vpn) {
+ if (data->vpn_phy_index >= 0)
+ connman_inet_del_host_route(data->vpn_phy_index,
+ data->ipv4_gateway);
+ return connman_inet_clear_gateway_address(data->index,
+ data->vpn_ip);
+ } else if (g_strcmp0(data->ipv4_gateway, "0.0.0.0") == 0) {
+ return connman_inet_clear_gateway_interface(data->index);
+ } else {
+ connman_inet_del_ipv6_host_route(data->index,
+ data->ipv6_gateway);
+ connman_inet_clear_ipv6_gateway_address(data->index,
+ data->ipv6_gateway);
+ connman_inet_del_host_route(data->index, data->ipv4_gateway);
+ return connman_inet_clear_gateway_address(data->index,
+ data->ipv4_gateway);
}
-
- DBG("ifname %s", ifr.ifr_name);
-
- memset(&rt, 0, sizeof(rt));
- rt.rt_flags = RTF_UP | RTF_GATEWAY;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(gateway);
- memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
-
- err = ioctl(sk, SIOCDELRT, &rt);
- if (err < 0)
- connman_error("Removing default route failed (%s)",
- strerror(errno));
-
- close(sk);
-
- return err;
}
-static DBusConnection *connection;
-
-static void emit_default_signal(struct connman_element *element)
-{
- DBusMessage *signal;
- DBusMessageIter entry, value;
- const char *key = "Default";
-
- signal = dbus_message_new_signal(element->path,
- CONNMAN_CONNECTION_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
-
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &value);
- dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
- &element->enabled);
- dbus_message_iter_close_container(&entry, &value);
-
- g_dbus_send_message(connection, signal);
-}
-
-static void find_element(struct connman_element *element, gpointer user_data)
-{
- struct gateway_data *data = user_data;
-
- DBG("element %p name %s", element, element->name);
-
- if (data->element != NULL)
- return;
-
- if (element->index != data->index)
- return;
-
- data->element = element;
-}
-
-static struct gateway_data *add_gateway(int index, const char *gateway)
+static struct gateway_data *add_gateway(struct connman_service *service,
+ int index, const char *ipv4_gateway,
+ const char *ipv6_gateway)
{
struct gateway_data *data;
- struct connman_service *service;
+
+ if (strlen(ipv4_gateway) == 0)
+ return NULL;
data = g_try_new0(struct gateway_data, 1);
if (data == NULL)
return NULL;
data->index = index;
- data->gateway = g_strdup(gateway);
+ data->ipv4_gateway = g_strdup(ipv4_gateway);
+ data->ipv6_gateway = g_strdup(ipv6_gateway);
data->active = FALSE;
- data->element = NULL;
-
- __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION,
- find_element, data);
+ data->vpn_ip = NULL;
+ data->vpn = FALSE;
+ data->vpn_phy_index = -1;
+ data->service = service;
- service = __connman_element_get_service(data->element);
data->order = __connman_service_get_order(service);
- gateway_list = g_slist_append(gateway_list, data);
+ g_hash_table_replace(gateway_hash, service, data);
return data;
}
static void set_default_gateway(struct gateway_data *data)
{
- struct connman_element *element = data->element;
- struct connman_service *service = NULL;
+ int index;
+
+ DBG("gateway %s", data->ipv4_gateway);
- DBG("gateway %s", data->gateway);
+ if (data->vpn == TRUE) {
+ connman_inet_set_gateway_address(data->index,
+ data->vpn_ip);
+ data->active = TRUE;
+
+ __connman_service_indicate_default(data->service);
- if (set_route(element, data->gateway) < 0)
return;
+ }
+
+ index = __connman_service_get_index(data->service);
+
+ if (g_strcmp0(data->ipv4_gateway, "0.0.0.0") == 0) {
+ if (connman_inet_set_gateway_interface(index) < 0)
+ return;
+ goto done;
+ }
- service = __connman_element_get_service(element);
- __connman_service_indicate_default(service);
+ connman_inet_set_ipv6_gateway_address(index, data->ipv6_gateway);
+ if (connman_inet_set_gateway_address(index, data->ipv4_gateway) < 0)
+ return;
+
+done:
+ __connman_service_indicate_default(data->service);
}
static struct gateway_data *find_default_gateway(void)
{
struct gateway_data *found = NULL;
unsigned int order = 0;
- GSList *list;
+ GHashTableIter iter;
+ gpointer value, key;
+
+ g_hash_table_iter_init(&iter, gateway_hash);
- for (list = gateway_list; list; list = list->next) {
- struct gateway_data *data = list->data;
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct gateway_data *data = value;
if (found == NULL || data->order > order) {
found = data;
return found;
}
-static void remove_gateway(struct gateway_data *data)
+static int disable_gateway(struct gateway_data *data)
{
- DBG("gateway %s", data->gateway);
+ if (data->active == TRUE)
+ return del_routes(data);
- gateway_list = g_slist_remove(gateway_list, data);
+ return 0;
+}
- if (data->active == TRUE)
- del_route(data->element, data->gateway);
+static void remove_gateway(gpointer user_data)
+{
+ struct gateway_data *data = user_data;
+
+ DBG("gateway %s", data->ipv4_gateway);
- g_free(data->gateway);
+ g_free(data->ipv4_gateway);
+ g_free(data->ipv6_gateway);
+ g_free(data->vpn_ip);
g_free(data);
}
.delgateway = connection_delgateway,
};
-static DBusMessage *get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct connman_element *element = data;
- DBusMessage *reply;
- DBusMessageIter array, dict;
- connman_uint8_t strength;
- const char *device, *network;
- const char *type;
-
- DBG("conn %p", conn);
-
- if (__connman_security_check_privilege(msg,
- CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
- return __connman_error_permission_denied(msg);
-
- reply = dbus_message_new_method_return(msg);
- if (reply == NULL)
- return NULL;
-
- dbus_message_iter_init_append(reply, &array);
-
- dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- type = connman_element_get_string(element, "Type");
- if (type != NULL)
- connman_dbus_dict_append_variant(&dict, "Type",
- DBUS_TYPE_STRING, &type);
-
- strength = connman_element_get_uint8(element, "Strength");
- if (strength > 0)
- connman_dbus_dict_append_variant(&dict, "Strength",
- DBUS_TYPE_BYTE, &strength);
-
- if (element->devname != NULL)
- connman_dbus_dict_append_variant(&dict, "Interface",
- DBUS_TYPE_STRING, &element->devname);
-
- connman_dbus_dict_append_variant(&dict, "Default",
- DBUS_TYPE_BOOLEAN, &element->enabled);
-
- device = __connman_element_get_device_path(element);
- if (device != NULL)
- connman_dbus_dict_append_variant(&dict, "Device",
- DBUS_TYPE_OBJECT_PATH, &device);
-
- network = __connman_element_get_network_path(element);
- if (network != NULL)
- connman_dbus_dict_append_variant(&dict, "Network",
- DBUS_TYPE_OBJECT_PATH, &network);
-
- __connman_element_append_ipv4(element, &dict);
-
- dbus_message_iter_close_container(&array, &dict);
-
- return reply;
-}
-
-static DBusMessage *set_property(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- DBusMessageIter iter, value;
- const char *name;
- int type;
-
- DBG("conn %p", conn);
-
- if (dbus_message_iter_init(msg, &iter) == FALSE)
- return __connman_error_invalid_arguments(msg);
-
- dbus_message_iter_get_basic(&iter, &name);
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &value);
-
- if (__connman_security_check_privilege(msg,
- CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
- return __connman_error_permission_denied(msg);
-
- type = dbus_message_iter_get_arg_type(&value);
-
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
-}
-
-static GDBusMethodTable connection_methods[] = {
- { "GetProperties", "", "a{sv}", get_properties },
- { "SetProperty", "sv", "", set_property },
- { },
-};
-
-static GDBusSignalTable connection_signals[] = {
- { "PropertyChanged", "sv" },
- { },
-};
-
-static void append_connections(DBusMessageIter *entry)
-{
- DBusMessageIter value, iter;
- const char *key = "Connections";
-
- dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
-
- dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
- DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
- &value);
-
- dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
- __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
- dbus_message_iter_close_container(&value, &iter);
-
- dbus_message_iter_close_container(entry, &value);
-}
-
-static void emit_connections_signal(void)
+static struct gateway_data *find_active_gateway(void)
{
- DBusMessage *signal;
- DBusMessageIter entry;
+ GHashTableIter iter;
+ gpointer value, key;
DBG("");
- signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
- CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &entry);
+ g_hash_table_iter_init(&iter, gateway_hash);
- append_connections(&entry);
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct gateway_data *data = value;
- g_dbus_send_message(connection, signal);
-}
-
-static int register_interface(struct connman_element *element)
-{
- DBG("element %p name %s path %s",
- element, element->name, element->path);
-
- if (g_dbus_register_interface(connection, element->path,
- CONNMAN_CONNECTION_INTERFACE,
- connection_methods, connection_signals,
- NULL, element, NULL) == FALSE) {
- connman_error("Failed to register %s connection", element->path);
- return -EIO;
+ if (data->active == TRUE)
+ return data;
}
- emit_connections_signal();
-
- return 0;
+ return NULL;
}
-static void unregister_interface(struct connman_element *element)
+static void update_order(void)
{
- DBG("element %p name %s", element, element->name);
+ GHashTableIter iter;
+ gpointer value, key;
- emit_connections_signal();
+ DBG("");
- g_dbus_unregister_interface(connection, element->path,
- CONNMAN_CONNECTION_INTERFACE);
-}
+ g_hash_table_iter_init(&iter, gateway_hash);
-static struct gateway_data *find_active_gateway(void)
-{
- GSList *list;
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct gateway_data *data = value;
- DBG("");
-
- for (list = gateway_list; list; list = list->next) {
- struct gateway_data *data = list->data;
- if (data->active == TRUE)
- return data;
+ data->order = __connman_service_get_order(data->service);
}
-
- return NULL;
}
-static int connection_probe(struct connman_element *element)
+int __connman_connection_gateway_add(struct connman_service *service,
+ const char *ipv4_gateway,
+ const char *ipv6_gateway,
+ const char *peer)
{
- struct connman_service *service = NULL;
- const char *gateway = NULL;
struct gateway_data *active_gateway = NULL;
struct gateway_data *new_gateway = NULL;
+ int index;
- DBG("element %p name %s", element, element->name);
+ index = __connman_service_get_index(service);
- if (element->parent == NULL)
- return -ENODEV;
+ DBG("service %p index %d ipv4 gateway %s ipv6 gateway %s vpn ip %s",
+ service, index, ipv4_gateway, ipv6_gateway, peer);
- if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
- return -ENODEV;
+ /*
+ * If gateway is NULL, it's a point to point link and the default
+ * gateway is 0.0.0.0, meaning the interface.
+ */
+ if (ipv4_gateway == NULL)
+ ipv4_gateway = "0.0.0.0";
- connman_element_get_value(element,
- CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
+ active_gateway = find_active_gateway();
+ new_gateway = add_gateway(service, index, ipv4_gateway, ipv6_gateway);
+ if (new_gateway == NULL)
+ return 0;
- DBG("gateway %s", gateway);
+ if (new_gateway->ipv6_gateway) {
+ connman_inet_add_ipv6_host_route(index,
+ new_gateway->ipv6_gateway,
+ NULL);
+ }
- if (register_interface(element) < 0)
- return -ENODEV;
+ if (g_strcmp0(new_gateway->ipv4_gateway, "0.0.0.0") != 0) {
+ connman_inet_add_host_route(index,
+ new_gateway->ipv4_gateway,
+ NULL);
+ }
- service = __connman_element_get_service(element);
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY);
+ __connman_service_nameserver_add_routes(service,
+ new_gateway->ipv4_gateway);
- connman_element_set_enabled(element, TRUE);
- emit_default_signal(element);
+ __connman_service_set_ipconfig_ready(service, CONNMAN_IPCONFIG_TYPE_IPV4);
- if (gateway == NULL)
- return 0;
+ if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_VPN) {
+ new_gateway->vpn = TRUE;
+ if (peer != NULL)
+ new_gateway->vpn_ip = g_strdup(peer);
+ else if (ipv4_gateway != NULL)
+ new_gateway->vpn_ip = g_strdup(ipv4_gateway);
+ else
+ new_gateway->vpn_ip = g_strdup(ipv6_gateway);
- active_gateway = find_active_gateway();
- new_gateway = add_gateway(element->index, gateway);
+ if (active_gateway)
+ new_gateway->vpn_phy_index = active_gateway->index;
+ } else {
+ new_gateway->vpn = FALSE;
+ }
if (active_gateway == NULL) {
set_default_gateway(new_gateway);
return 0;
}
- if (new_gateway->order >= active_gateway->order) {
- del_route(active_gateway->element, active_gateway->gateway);
- return 0;
+ if (new_gateway->vpn == TRUE) {
+ connman_inet_add_host_route(active_gateway->index,
+ new_gateway->ipv4_gateway,
+ active_gateway->ipv4_gateway);
+ connman_inet_clear_gateway_address(active_gateway->index,
+ active_gateway->ipv4_gateway);
}
return 0;
}
-static void connection_remove(struct connman_element *element)
+void __connman_connection_gateway_remove(struct connman_service *service)
{
- struct connman_service *service;
- const char *gateway = NULL;
struct gateway_data *data = NULL;
+ gboolean set_default = FALSE;
+ int err;
- DBG("element %p name %s", element, element->name);
-
- service = __connman_element_get_service(element);
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_DISCONNECT);
+ DBG("service %p", service);
- connman_element_set_enabled(element, FALSE);
- emit_default_signal(element);
+ __connman_service_nameserver_del_routes(service);
- unregister_interface(element);
+ data = g_hash_table_lookup(gateway_hash, service);
+ if (data == NULL)
+ return;
- connman_element_get_value(element,
- CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
+ set_default = data->vpn;
- DBG("gateway %s", gateway);
+ if (data->vpn == TRUE && data->index >= 0) {
+ connman_inet_del_host_route(data->index,
+ data->ipv4_gateway);
+ }
- if (gateway == NULL)
- return;
+ __connman_service_nameserver_del_routes(service);
- data = find_gateway(element->index, gateway);
- if (data == NULL)
- return;
+ err = disable_gateway(data);
+ g_hash_table_remove(gateway_hash, service);
- remove_gateway(data);
+ /* with vpn this will be called after the network was deleted,
+ * we need to call set_default here because we will not recieve any
+ * gateway delete notification.
+ * We hit the same issue if remove_gateway() fails.
+ */
+ if (set_default || err < 0) {
+ data = find_default_gateway();
+ if (data != NULL)
+ set_default_gateway(data);
+ }
}
-static struct connman_driver connection_driver = {
- .name = "connection",
- .type = CONNMAN_ELEMENT_TYPE_CONNECTION,
- .priority = CONNMAN_DRIVER_PRIORITY_LOW,
- .probe = connection_probe,
- .remove = connection_remove,
-};
-
-int __connman_connection_init(void)
+gboolean __connman_connection_update_gateway(void)
{
- DBG("");
+ struct gateway_data *active_gateway, *default_gateway;
+ gboolean updated = FALSE;
- connection = connman_dbus_get_connection();
+ if (gateway_hash == NULL)
+ return updated;
- if (connman_rtnl_register(&connection_rtnl) < 0)
- connman_error("Failed to setup RTNL gateway driver");
+ update_order();
- return connman_driver_register(&connection_driver);
+ active_gateway = find_active_gateway();
+ default_gateway = find_default_gateway();
+
+ if (active_gateway && active_gateway != default_gateway)
+ updated = TRUE;
+
+ return updated;
}
-void __connman_connection_cleanup(void)
+int __connman_connection_init(void)
{
- GSList *list;
+ int err;
DBG("");
- connman_driver_unregister(&connection_driver);
+ gateway_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, remove_gateway);
- connman_rtnl_unregister(&connection_rtnl);
-
- for (list = gateway_list; list; list = list->next) {
- struct gateway_data *data = list->data;
-
- DBG("index %d gateway %s", data->index, data->gateway);
-
- g_free(data->gateway);
- g_free(data);
- list->data = NULL;
- }
-
- g_slist_free(gateway_list);
- gateway_list = NULL;
+ err = connman_rtnl_register(&connection_rtnl);
+ if (err < 0)
+ connman_error("Failed to setup RTNL gateway driver");
- dbus_connection_unref(connection);
+ return err;
}
-static void update_order(void)
+void __connman_connection_cleanup(void)
{
- GSList *list = NULL;
-
- for (list = gateway_list; list; list = list->next) {
- struct gateway_data *data = list->data;
- struct connman_service *service;
+ GHashTableIter iter;
+ gpointer value, key;
- service = __connman_element_get_service(data->element);
- data->order = __connman_service_get_order(service);
- }
-}
+ DBG("");
-gboolean __connman_connection_update_gateway(void)
-{
- struct gateway_data *active_gateway, *default_gateway;
- gboolean updated = FALSE;
+ connman_rtnl_unregister(&connection_rtnl);
- update_order();
+ g_hash_table_iter_init(&iter, gateway_hash);
- active_gateway = find_active_gateway();
- default_gateway = find_default_gateway();
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct gateway_data *data = value;
- if (active_gateway && active_gateway != default_gateway) {
- del_route(active_gateway->element, active_gateway->gateway);
- updated = TRUE;
+ disable_gateway(data);
}
- return updated;
+ g_hash_table_destroy(gateway_hash);
+ gateway_hash = NULL;
}