summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-04-03 14:07:24 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-04-12 11:00:42 +0300
commit709aaebeaca495292306f95d3fb1bc346f331d67 (patch)
tree476e790b61bf7b7fae4645828029abadcf38d3ff /src
parent4ca9544819ca979354dabdf24f4f4f42c2a416d5 (diff)
downloadconnman-709aaebeaca495292306f95d3fb1bc346f331d67.tar.gz
connman-709aaebeaca495292306f95d3fb1bc346f331d67.tar.bz2
connman-709aaebeaca495292306f95d3fb1bc346f331d67.zip
provider: Disconnect VPN when phy service is disconnected
If the VPN is connected and the underlaying service is disconnected, then we must also disconnect the VPN if it is still connected.
Diffstat (limited to 'src')
-rw-r--r--src/connection.c22
-rw-r--r--src/connman.h1
-rw-r--r--src/provider.c62
3 files changed, 85 insertions, 0 deletions
diff --git a/src/connection.c b/src/connection.c
index 3747c051..8b1b689d 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1025,6 +1025,28 @@ gboolean __connman_connection_update_gateway(void)
return updated;
}
+int __connman_connection_get_vpn_index(int phy_index)
+{
+ GHashTableIter iter;
+ gpointer value, key;
+
+ 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->ipv4_gateway != NULL &&
+ data->ipv4_gateway->vpn_phy_index == phy_index)
+ return data->index;
+
+ if (data->ipv6_gateway != NULL &&
+ data->ipv6_gateway->vpn_phy_index == phy_index)
+ return data->index;
+ }
+
+ return -1;
+}
+
int __connman_connection_init(void)
{
int err;
diff --git a/src/connman.h b/src/connman.h
index 306e9d66..7f42bc99 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -402,6 +402,7 @@ int __connman_connection_gateway_add(struct connman_service *service,
const char *peer);
void __connman_connection_gateway_remove(struct connman_service *service,
enum connman_ipconfig_type type);
+int __connman_connection_get_vpn_index(int phy_index);
gboolean __connman_connection_update_gateway(void);
void __connman_connection_gateway_activate(struct connman_service *service,
diff --git a/src/provider.c b/src/provider.c
index 42fd112f..00f3f4c5 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -1281,9 +1281,71 @@ static void provider_offline_mode(connman_bool_t enabled)
}
+static struct connman_provider *provider_get(int index)
+{
+ GHashTableIter iter;
+ gpointer value, key;
+
+ g_hash_table_iter_init(&iter, provider_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct connman_provider *provider = value;
+
+ if (provider->index == index)
+ return provider;
+ }
+
+ return NULL;
+}
+
+static void provider_service_changed(struct connman_service *service,
+ enum connman_service_state state)
+{
+ struct connman_provider *provider;
+ int vpn_index, service_index;
+
+ if (service == NULL)
+ return;
+
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ return;
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ break;
+ }
+
+ service_index = __connman_service_get_index(service);
+
+ vpn_index = __connman_connection_get_vpn_index(service_index);
+
+ DBG("service %p %s state %d index %d/%d", service,
+ __connman_service_get_ident(service),
+ state, service_index, vpn_index);
+
+ if (vpn_index < 0)
+ return;
+
+ provider = provider_get(vpn_index);
+ if (provider == NULL)
+ return;
+
+ DBG("disconnect %p index %d", provider, vpn_index);
+
+ __connman_provider_disconnect(provider);
+
+ return;
+}
+
static struct connman_notifier provider_notifier = {
.name = "provider",
.offline_mode = provider_offline_mode,
+ .service_state_changed = provider_service_changed,
};
int __connman_provider_init(void)