summaryrefslogtreecommitdiff
path: root/vpn
diff options
context:
space:
mode:
authorZhang zhengguang <zhengguang.zhang@intel.com>2014-10-29 11:03:47 +0800
committerZhang zhengguang <zhengguang.zhang@intel.com>2014-10-29 11:03:47 +0800
commitbcae74da8fa2958b3fec9153fc33e41f0e0317bf (patch)
tree06a00f6457307467fee4f6580dce4a1a857751c1 /vpn
parent1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7 (diff)
downloadconnman-bcae74da8fa2958b3fec9153fc33e41f0e0317bf.tar.gz
connman-bcae74da8fa2958b3fec9153fc33e41f0e0317bf.tar.bz2
connman-bcae74da8fa2958b3fec9153fc33e41f0e0317bf.zip
Imported Upstream version 1.26upstream/1.26
Diffstat (limited to 'vpn')
-rw-r--r--vpn/plugins/l2tp.c2
-rw-r--r--vpn/plugins/openconnect.c1
-rw-r--r--vpn/plugins/openvpn.c2
-rw-r--r--vpn/plugins/pptp.c2
-rw-r--r--vpn/plugins/vpn.c29
-rw-r--r--vpn/plugins/vpn.h2
-rw-r--r--vpn/plugins/vpnc.c2
-rw-r--r--vpn/vpn-ipconfig.c24
-rw-r--r--vpn/vpn-provider.c117
-rw-r--r--vpn/vpn-provider.h2
-rw-r--r--vpn/vpn.h2
11 files changed, 136 insertions, 49 deletions
diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c
index 91acc85f..22f9dcf8 100644
--- a/vpn/plugins/l2tp.c
+++ b/vpn/plugins/l2tp.c
@@ -2,7 +2,7 @@
*
* ConnMan VPN daemon
*
- * Copyright (C) 2010,2013 BMW Car IT GmbH. All rights reserved.
+ * Copyright (C) 2010,2013 BMW Car IT GmbH.
* Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/vpn/plugins/openconnect.c b/vpn/plugins/openconnect.c
index c6b9cd65..5feaed9d 100644
--- a/vpn/plugins/openconnect.c
+++ b/vpn/plugins/openconnect.c
@@ -552,7 +552,6 @@ static int oc_error_code(struct vpn_provider *provider, int exit_code)
switch (exit_code) {
case 1:
- return VPN_PROVIDER_ERROR_CONNECT_FAILED;
case 2:
vpn_provider_set_string_hide_value(provider,
"OpenConnect.Cookie", NULL);
diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c
index 35013c40..9ee5795c 100644
--- a/vpn/plugins/openvpn.c
+++ b/vpn/plugins/openvpn.c
@@ -2,7 +2,7 @@
*
* ConnMan VPN daemon
*
- * Copyright (C) 2010 BMW Car IT GmbH. All rights reserved.
+ * Copyright (C) 2010-2014 BMW Car IT GmbH.
*
* 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
diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c
index a6e51e79..9f2a214d 100644
--- a/vpn/plugins/pptp.c
+++ b/vpn/plugins/pptp.c
@@ -2,7 +2,7 @@
*
* ConnMan VPN daemon
*
- * Copyright (C) 2010,2013 BMW Car IT GmbH. All rights reserved.
+ * Copyright (C) 2010,2013-2014 BMW Car IT GmbH.
* Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c
index b407573e..b438d06e 100644
--- a/vpn/plugins/vpn.c
+++ b/vpn/plugins/vpn.c
@@ -138,9 +138,9 @@ void vpn_died(struct connman_task *task, int exit_code, void *user_data)
vpn_provider_set_data(provider, NULL);
if (data->watch != 0) {
- vpn_provider_unref(provider);
vpn_rtnl_remove_watch(data->watch);
data->watch = 0;
+ vpn_provider_unref(provider);
}
vpn_exit:
@@ -160,8 +160,6 @@ vpn_exit:
ret = VPN_PROVIDER_ERROR_UNKNOWN;
vpn_provider_indicate_error(provider, ret);
-
- vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
} else
vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
@@ -245,6 +243,31 @@ static DBusMessage *vpn_notify(struct connman_task *task,
switch (state) {
case VPN_STATE_CONNECT:
case VPN_STATE_READY:
+ if (data->state == VPN_STATE_READY) {
+ /*
+ * This is the restart case, in which case we must
+ * just set the IP address.
+ *
+ * We need to remove first the old address, just
+ * replacing the old address will not work as expected
+ * because the old address will linger in the interface
+ * and not disapper so the clearing is needed here.
+ *
+ * Also the state must change, otherwise the routes
+ * will not be set properly.
+ */
+ vpn_provider_set_state(provider,
+ VPN_PROVIDER_STATE_CONNECT);
+
+ vpn_provider_clear_address(provider, AF_INET);
+ vpn_provider_clear_address(provider, AF_INET6);
+
+ vpn_provider_change_address(provider);
+ vpn_provider_set_state(provider,
+ VPN_PROVIDER_STATE_READY);
+ break;
+ }
+
index = vpn_provider_get_index(provider);
vpn_provider_ref(provider);
data->watch = vpn_rtnl_add_newlink_watch(index,
diff --git a/vpn/plugins/vpn.h b/vpn/plugins/vpn.h
index 3d2b66c5..bf56728d 100644
--- a/vpn/plugins/vpn.h
+++ b/vpn/plugins/vpn.h
@@ -2,7 +2,7 @@
*
* ConnMan VPN daemon
*
- * Copyright (C) 2010 BMW Car IT GmbH. All rights reserved.
+ * Copyright (C) 2010,2014 BMW Car IT GmbH.
*
* 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
diff --git a/vpn/plugins/vpnc.c b/vpn/plugins/vpnc.c
index 04235c86..09674bd8 100644
--- a/vpn/plugins/vpnc.c
+++ b/vpn/plugins/vpnc.c
@@ -2,7 +2,7 @@
*
* ConnMan VPN daemon
*
- * Copyright (C) 2010,2013 BMW Car IT GmbH. All rights reserved.
+ * Copyright (C) 2010,2013 BMW Car IT GmbH.
* Copyright (C) 2010,2012-2013 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/vpn/vpn-ipconfig.c b/vpn/vpn-ipconfig.c
index c3e61453..c096fa37 100644
--- a/vpn/vpn-ipconfig.c
+++ b/vpn/vpn-ipconfig.c
@@ -69,27 +69,13 @@ struct vpn_ipdevice {
static GHashTable *ipdevice_hash = NULL;
-unsigned char __vpn_ipconfig_netmask_prefix_len(const char *netmask)
+struct connman_ipaddress *
+__vpn_ipconfig_get_address(struct vpn_ipconfig *ipconfig)
{
- unsigned char bits;
- in_addr_t mask;
- in_addr_t host;
-
- if (!netmask)
- return 32;
-
- mask = inet_network(netmask);
- host = ~mask;
-
- /* a valid netmask must be 2^n - 1 */
- if ((host & (host + 1)) != 0)
- return -1;
-
- bits = 0;
- for (; mask; mask <<= 1)
- ++bits;
+ if (!ipconfig)
+ return NULL;
- return bits;
+ return ipconfig->address;
}
const char *__vpn_ipconfig_get_peer(struct vpn_ipconfig *ipconfig)
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index c39ebf9d..16c0c2be 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -84,6 +84,8 @@ struct vpn_provider {
char *config_file;
char *config_entry;
bool immutable;
+ struct connman_ipaddress *prev_ipv4_addr;
+ struct connman_ipaddress *prev_ipv6_addr;
};
static void append_properties(DBusMessageIter *iter,
@@ -1000,6 +1002,8 @@ static void provider_destruct(struct vpn_provider *provider)
g_strfreev(provider->host_ip);
g_free(provider->config_file);
g_free(provider->config_entry);
+ connman_ipaddress_free(provider->prev_ipv4_addr);
+ connman_ipaddress_free(provider->prev_ipv6_addr);
g_free(provider);
}
@@ -1307,13 +1311,6 @@ static int provider_indicate_state(struct vpn_provider *provider,
VPN_CONNECTION_INTERFACE, "State",
DBUS_TYPE_STRING, &str);
- /*
- * We do not stay in failure state as clients like connmand can
- * get confused about our current state.
- */
- if (provider->state == VPN_PROVIDER_STATE_FAILURE)
- provider->state = VPN_PROVIDER_STATE_IDLE;
-
return 0;
}
@@ -1550,15 +1547,16 @@ int vpn_provider_indicate_error(struct vpn_provider *provider,
DBG("provider %p id %s error %d", provider, provider->identifier,
error);
+ vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
+
switch (error) {
- case VPN_PROVIDER_ERROR_LOGIN_FAILED:
- break;
- case VPN_PROVIDER_ERROR_AUTH_FAILED:
- vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
- break;
+ case VPN_PROVIDER_ERROR_UNKNOWN:
case VPN_PROVIDER_ERROR_CONNECT_FAILED:
break;
- default:
+
+ case VPN_PROVIDER_ERROR_LOGIN_FAILED:
+ case VPN_PROVIDER_ERROR_AUTH_FAILED:
+ vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
break;
}
@@ -2304,19 +2302,41 @@ int vpn_provider_set_ipaddress(struct vpn_provider *provider,
break;
}
- DBG("provider %p ipconfig %p family %d", provider, ipconfig,
- ipaddress->family);
+ DBG("provider %p state %d ipconfig %p family %d", provider,
+ provider->state, ipconfig, ipaddress->family);
if (!ipconfig)
return -EINVAL;
provider->family = ipaddress->family;
- __vpn_ipconfig_set_local(ipconfig, ipaddress->local);
- __vpn_ipconfig_set_peer(ipconfig, ipaddress->peer);
- __vpn_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
- __vpn_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
- __vpn_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
+ if (provider->state == VPN_PROVIDER_STATE_CONNECT ||
+ provider->state == VPN_PROVIDER_STATE_READY) {
+ struct connman_ipaddress *addr =
+ __vpn_ipconfig_get_address(ipconfig);
+
+ /*
+ * Remember the old address so that we can remove it in notify
+ * function in plugins/vpn.c if we ever restart
+ */
+ if (ipaddress->family == AF_INET6) {
+ connman_ipaddress_free(provider->prev_ipv6_addr);
+ provider->prev_ipv6_addr =
+ connman_ipaddress_copy(addr);
+ } else {
+ connman_ipaddress_free(provider->prev_ipv4_addr);
+ provider->prev_ipv4_addr =
+ connman_ipaddress_copy(addr);
+ }
+ }
+
+ if (ipaddress->local) {
+ __vpn_ipconfig_set_local(ipconfig, ipaddress->local);
+ __vpn_ipconfig_set_peer(ipconfig, ipaddress->peer);
+ __vpn_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
+ __vpn_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
+ __vpn_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
+ }
return 0;
}
@@ -2544,6 +2564,63 @@ const char *vpn_provider_get_path(struct vpn_provider *provider)
return provider->path;
}
+void vpn_provider_change_address(struct vpn_provider *provider)
+{
+ switch (provider->family) {
+ case AF_INET:
+ connman_inet_set_address(provider->index,
+ __vpn_ipconfig_get_address(provider->ipconfig_ipv4));
+ break;
+ case AF_INET6:
+ connman_inet_set_ipv6_address(provider->index,
+ __vpn_ipconfig_get_address(provider->ipconfig_ipv6));
+ break;
+ default:
+ break;
+ }
+}
+
+void vpn_provider_clear_address(struct vpn_provider *provider, int family)
+{
+ const char *address;
+ unsigned char len;
+
+ DBG("provider %p family %d ipv4 %p ipv6 %p", provider, family,
+ provider->prev_ipv4_addr, provider->prev_ipv6_addr);
+
+ switch (family) {
+ case AF_INET:
+ if (provider->prev_ipv4_addr) {
+ connman_ipaddress_get_ip(provider->prev_ipv4_addr,
+ &address, &len);
+
+ DBG("ipv4 %s/%d", address, len);
+
+ connman_inet_clear_address(provider->index,
+ provider->prev_ipv4_addr);
+ connman_ipaddress_free(provider->prev_ipv4_addr);
+ provider->prev_ipv4_addr = NULL;
+ }
+ break;
+ case AF_INET6:
+ if (provider->prev_ipv6_addr) {
+ connman_ipaddress_get_ip(provider->prev_ipv6_addr,
+ &address, &len);
+
+ DBG("ipv6 %s/%d", address, len);
+
+ connman_inet_clear_ipv6_address(provider->index,
+ address, len);
+
+ connman_ipaddress_free(provider->prev_ipv6_addr);
+ provider->prev_ipv6_addr = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
static int agent_probe(struct connman_agent *agent)
{
DBG("agent %p", agent);
diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h
index 22b2062d..8105d7f1 100644
--- a/vpn/vpn-provider.h
+++ b/vpn/vpn-provider.h
@@ -107,6 +107,8 @@ const char *vpn_provider_get_save_group(struct vpn_provider *provider);
const char *vpn_provider_get_name(struct vpn_provider *provider);
const char *vpn_provider_get_host(struct vpn_provider *provider);
const char *vpn_provider_get_path(struct vpn_provider *provider);
+void vpn_provider_change_address(struct vpn_provider *provider);
+void vpn_provider_clear_address(struct vpn_provider *provider, int family);
typedef void (* vpn_provider_connect_cb_t) (struct vpn_provider *provider,
void *user_data, int error);
diff --git a/vpn/vpn.h b/vpn/vpn.h
index 3fca03cc..8bf86bd1 100644
--- a/vpn/vpn.h
+++ b/vpn/vpn.h
@@ -32,7 +32,7 @@ void __vpn_manager_cleanup(void);
struct vpn_ipconfig;
-unsigned char __vpn_ipconfig_netmask_prefix_len(const char *netmask);
+struct connman_ipaddress *__vpn_ipconfig_get_address(struct vpn_ipconfig *ipconfig);
unsigned short __vpn_ipconfig_get_type_from_index(int index);
unsigned int __vpn_ipconfig_get_flags_from_index(int index);
void __vpn_ipconfig_foreach(void (*function) (int index,