From: Daniel Wagner <[email protected]>

We should add the routing entries pushed by the OpenVPN server.
---
 include/inet.h     |    3 ++-
 include/provider.h |    4 ++++
 src/connection.c   |    5 +++--
 src/inet.c         |   13 ++++++++++---
 src/provider.c     |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 src/service.c      |    6 ++++--
 6 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/include/inet.h b/include/inet.h
index 7b34900..cdcd87b 100644
--- a/include/inet.h
+++ b/include/inet.h
@@ -46,7 +46,8 @@ connman_bool_t connman_inet_is_cfg80211(int index);
 
 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress);
 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress);
-int connman_inet_add_host_route(int index, const char *host, const char 
*gateway);
+int connman_inet_add_host_route(int index, const char *host, const char 
*gateway,
+                               const char *netmask);
 int connman_inet_del_host_route(int index, const char *host);
 int connman_inet_set_gateway_address(int index, const char *gateway);
 int connman_inet_clear_gateway_address(int index, const char *gateway);
diff --git a/include/provider.h b/include/provider.h
index dde37fb..569d47f 100644
--- a/include/provider.h
+++ b/include/provider.h
@@ -83,6 +83,10 @@ void connman_provider_set_dns(struct connman_provider 
*provider,
 void connman_provider_set_domain(struct connman_provider *provider,
                                                        const char *domain);
 
+int connman_provider_append_route(struct connman_provider *provider,
+                                       const char *host, const char *netmask,
+                                       const char *gateway);
+
 const char *connman_provider_get_driver_name(struct connman_provider 
*provider);
 
 struct connman_provider_driver {
diff --git a/src/connection.c b/src/connection.c
index bac700f..0a6d90e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -323,7 +323,7 @@ static int connection_probe(struct connman_element *element)
        connman_inet_add_ipv6_host_route(element->index,
                                        new_gateway->ipv6_gateway, NULL);
        connman_inet_add_host_route(element->index,
-                                       new_gateway->ipv4_gateway, NULL);
+                                       new_gateway->ipv4_gateway, NULL, NULL);
        __connman_service_nameserver_add_routes(service,
                                                new_gateway->ipv4_gateway);
        __connman_service_set_domainname(service, domainname);
@@ -348,7 +348,8 @@ static int connection_probe(struct connman_element *element)
        if (new_gateway->vpn == TRUE) {
                connman_inet_add_host_route(active_gateway->index,
                                                new_gateway->ipv4_gateway,
-                                               active_gateway->ipv4_gateway);
+                                               active_gateway->ipv4_gateway,
+                                               NULL);
        }
 
        if (new_gateway->order >= active_gateway->order) {
diff --git a/src/inet.c b/src/inet.c
index 419126b..1834d94 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -616,7 +616,9 @@ int connman_inet_clear_address(int index, struct 
connman_ipaddress *ipaddress)
        return 0;
 }
 
-int connman_inet_add_host_route(int index, const char *host, const char 
*gateway)
+int connman_inet_add_host_route(int index, const char *host,
+                               const char *gateway,
+                               const char *netmask)
 {
        struct ifreq ifr;
        struct rtentry rt;
@@ -638,9 +640,11 @@ int connman_inet_add_host_route(int index, const char 
*host, const char *gateway
        DBG("ifname %s", ifr.ifr_name);
 
        memset(&rt, 0, sizeof(rt));
-       rt.rt_flags = RTF_UP | RTF_HOST;
+       rt.rt_flags = RTF_UP;
        if (gateway != NULL)
                rt.rt_flags |= RTF_GATEWAY;
+       if (netmask == NULL)
+               rt.rt_flags |= RTF_HOST;
 
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
@@ -657,7 +661,10 @@ int connman_inet_add_host_route(int index, const char 
*host, const char *gateway
 
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
-       addr.sin_addr.s_addr = INADDR_ANY;
+       if (netmask != NULL)
+               addr.sin_addr.s_addr = inet_addr(netmask);
+       else
+               addr.sin_addr.s_addr = INADDR_ANY;
        memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
 
        rt.rt_dev = ifr.ifr_name;
diff --git a/src/provider.c b/src/provider.c
index ea7d37b..0a9cfa8 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -35,6 +35,12 @@ static GHashTable *provider_hash = NULL;
 
 static GSList *driver_list = NULL;
 
+struct connman_route {
+       char *host;
+       char *netmask;
+       char *gateway;
+};
+
 struct connman_provider {
        struct connman_element element;
        struct connman_service *vpn_service;
@@ -44,6 +50,7 @@ struct connman_provider {
        char *host;
        char *dns;
        char *domain;
+       GSList *route_list;
        struct connman_provider_driver *driver;
        void *driver_data;
 };
@@ -261,6 +268,7 @@ static int set_connected(struct connman_provider *provider,
                char *nameservers = NULL, *name = NULL;
                const char *value;
                char *second_ns;
+               GSList *list;
                int err;
 
                __connman_service_indicate_state(provider->vpn_service,
@@ -312,6 +320,15 @@ static int set_connected(struct connman_provider *provider,
                g_free(nameservers);
                g_free(name);
 
+               for (list = provider->route_list; list; list = list->next) {
+                       struct connman_route *route = list->data;
+
+                       connman_inet_add_host_route(provider->element.index,
+                                                       route->host,
+                                                       route->gateway,
+                                                       route->netmask);
+                       /* XXX How to handle IPv6?  */
+               }
        } else {
                connman_element_unregister_children(&provider->element);
                __connman_service_indicate_state(service,
@@ -365,6 +382,7 @@ static void unregister_provider(gpointer data)
 static void provider_destruct(struct connman_element *element)
 {
        struct connman_provider *provider = element->private;
+       GSList *list;
 
        DBG("provider %p", provider);
 
@@ -373,6 +391,15 @@ static void provider_destruct(struct connman_element 
*element)
        g_free(provider->domain);
        g_free(provider->identifier);
        g_free(provider->dns);
+
+       for (list = provider->route_list; list; list = list->next) {
+               struct connman_route *route = list->data;
+
+               g_free(route->host);
+               g_free(route->netmask);
+               g_free(route->gateway);
+       }
+       g_slist_free(provider->route_list);
 }
 
 static void provider_initialize(struct connman_provider *provider)
@@ -395,6 +422,7 @@ static void provider_initialize(struct connman_provider 
*provider)
        provider->dns = NULL;
        provider->domain = NULL;
        provider->identifier = NULL;
+       provider->route_list = NULL;
 }
 
 static struct connman_provider *connman_provider_new(void)
@@ -694,6 +722,25 @@ int connman_provider_get_index(struct connman_provider 
*provider)
        return provider->element.index;
 }
 
+int connman_provider_append_route(struct connman_provider *provider,
+                                       const char *host, const char *netmask,
+                                       const char *gateway)
+{
+       struct connman_route *route;
+
+       route = g_try_new0(struct connman_route, 1);
+       if (route == NULL)
+               return -ENOMEM;
+
+       route->host = g_strdup(host);
+       route->netmask = g_strdup(netmask);
+       route->gateway = g_strdup(gateway);
+
+       provider->route_list = g_slist_append(provider->route_list, route);
+
+       return TRUE;
+}
+
 const char *connman_provider_get_driver_name(struct connman_provider *provider)
 {
        return provider->driver->name;
diff --git a/src/service.c b/src/service.c
index 626cd31..28ac88a 100644
--- a/src/service.c
+++ b/src/service.c
@@ -436,13 +436,15 @@ void __connman_service_nameserver_add_routes(struct 
connman_service *service,
                                continue;
 
                        connman_inet_add_host_route(index,
-                                               service->nameservers[i], gw);
+                                                       service->nameservers[i],
+                                                       gw, NULL);
                }
        } else if (service->nameserver != NULL) {
                if (connman_inet_compare_subnet(index, service->nameserver))
                        return;
 
-               connman_inet_add_host_route(index, service->nameserver, gw);
+               connman_inet_add_host_route(index, service->nameserver,
+                                               gw, NULL);
        }
 }
 
-- 
1.7.3.2

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to