summaryrefslogtreecommitdiff
path: root/src/provider.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-08-08 13:22:48 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-08-09 12:16:56 +0300
commit66167bb34d24e5c66e26a0d45d7b70a664eb793f (patch)
tree7ff648a1ce9c517438029f1a83f664511d0d687f /src/provider.c
parent2c5ca690ed80403f54229b005bc11cf87ba3e65b (diff)
downloadconnman-66167bb34d24e5c66e26a0d45d7b70a664eb793f.tar.gz
connman-66167bb34d24e5c66e26a0d45d7b70a664eb793f.tar.bz2
connman-66167bb34d24e5c66e26a0d45d7b70a664eb793f.zip
provider: Discard routes to VPN server via VPN tunnel
These obsolete routes must be discarded as we cannot contact VPN server via VPN tunnel. If the VPN server address is not yet resolved, we do that while starting the VPN client process. Example of non working routes: Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 0.0.0.0 0.0.0.0 UG 0 0 0 vpn0 10.10.15.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0 10.10.15.1 0.0.0.0 255.255.255.255 UH 0 0 0 wlan0 10.252.112.0 0.0.0.0 255.255.240.0 U 0 0 0 vpn0 193.229.0.40 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0 193.229.0.42 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0 113.108.211.91 0.0.0.0 255.255.255.255 UH 0 0 0 vpn0 113.108.211.91 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0 The correct routes should be like this: Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 0.0.0.0 0.0.0.0 U 0 0 0 vpn0 10.10.15.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0 10.10.15.1 0.0.0.0 255.255.255.255 UH 0 0 0 wlan0 10.252.112.0 0.0.0.0 255.255.240.0 U 0 0 0 vpn0 193.229.0.40 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0 193.229.0.42 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0 113.108.211.91 10.10.15.1 255.255.255.255 UGH 0 0 0 wlan0
Diffstat (limited to 'src/provider.c')
-rw-r--r--src/provider.c86
1 files changed, 84 insertions, 2 deletions
diff --git a/src/provider.c b/src/provider.c
index ebc70557..76e84789 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdlib.h>
#include <gdbus.h>
+#include <gweb/gresolv.h>
#include "connman.h"
@@ -61,8 +62,55 @@ struct connman_provider {
GHashTable *user_routes;
gchar **user_networks;
gsize num_user_networks;
+ GResolv *resolv;
+ char **host_ip;
};
+static void resolv_result(GResolvResultStatus status,
+ char **results, gpointer user_data)
+{
+ struct connman_provider *provider = user_data;
+
+ DBG("status %d", status);
+
+ if (status == G_RESOLV_RESULT_STATUS_SUCCESS && results != NULL &&
+ g_strv_length(results) > 0)
+ provider->host_ip = g_strdupv(results);
+
+ connman_provider_unref(provider);
+}
+
+static void provider_resolv_host_addr(struct connman_provider *provider)
+{
+ if (provider->host == NULL)
+ return;
+
+ if (connman_inet_check_ipaddress(provider->host) > 0)
+ return;
+
+ if (provider->host_ip != NULL)
+ return;
+
+ /*
+ * If the hostname is not numeric, try to resolv it. We do not wait
+ * the result as it might take some time. We will get the result
+ * before VPN will feed routes to us because VPN client will need
+ * the IP address also before VPN connection can be established.
+ */
+ provider->resolv = g_resolv_new(0);
+ if (provider->resolv == NULL) {
+ DBG("Cannot resolv %s", provider->host);
+ return;
+ }
+
+ DBG("Trying to resolv %s", provider->host);
+
+ connman_provider_ref(provider);
+
+ g_resolv_lookup_hostname(provider->resolv, provider->host,
+ resolv_result, provider);
+}
+
void __connman_provider_append_properties(struct connman_provider *provider,
DBusMessageIter *iter)
{
@@ -350,6 +398,11 @@ static void provider_destruct(struct connman_provider *provider)
g_hash_table_destroy(provider->routes);
g_hash_table_destroy(provider->user_routes);
g_hash_table_destroy(provider->setting_strings);
+ if (provider->resolv != NULL) {
+ g_resolv_unref(provider->resolv);
+ provider->resolv = NULL;
+ }
+ g_strfreev(provider->host_ip);
g_free(provider);
}
@@ -410,9 +463,10 @@ int __connman_provider_connect(struct connman_provider *provider)
DBG("provider %p", provider);
- if (provider->driver != NULL && provider->driver->connect != NULL)
+ if (provider->driver != NULL && provider->driver->connect != NULL) {
+ provider_resolv_host_addr(provider);
err = provider->driver->connect(provider);
- else
+ } else
return -EOPNOTSUPP;
if (err < 0) {
@@ -459,6 +513,21 @@ int __connman_provider_remove(const char *path)
return -ENXIO;
}
+static connman_bool_t check_host(char **hosts, char *host)
+{
+ int i;
+
+ if (hosts == NULL)
+ return FALSE;
+
+ for (i = 0; hosts[i] != NULL; i++) {
+ if (g_strcmp0(hosts[i], host) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void provider_append_routes(gpointer key, gpointer value,
gpointer user_data)
{
@@ -466,6 +535,17 @@ static void provider_append_routes(gpointer key, gpointer value,
struct connman_provider *provider = user_data;
int index = provider->index;
+ /*
+ * 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->host) == TRUE) {
+ DBG("Discarding VPN route to %s via %s at index %d",
+ route->host, route->gateway, index);
+ return;
+ }
+
if (route->family == AF_INET6) {
unsigned char prefix_len = atoi(route->netmask);
@@ -881,6 +961,8 @@ int __connman_provider_create_and_connect(DBusMessage *msg)
if (provider_register(provider) == 0)
connman_provider_load(provider);
+
+ provider_resolv_host_addr(provider);
}
if (networks != NULL) {