Host routes are added for nameservers whenever the nameservers for
a service are updated.  The ensures that nameservers are always
reachable as long as a service is online, even if the default
route changes.

In particular, this fixes problems with the DNS proxy when the
nameservers are not on a local subnet.  Since nameservers are added,
to the resolver before the default route is set up, the DNS proxy
would fail to connect to the nameservers as they were not yet
reachable.
---
 include/inet.h   |    2 +-
 src/connection.c |    2 +-
 src/inet.c       |    6 +++++-
 src/service.c    |   45 +++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/include/inet.h b/include/inet.h
index b5bf8a5..009f7e6 100644
--- a/include/inet.h
+++ b/include/inet.h
@@ -44,7 +44,7 @@ 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);
-int connman_inet_add_host_route_vpn(int index, const char *gateway, const char 
*host);
+int connman_inet_add_host_route_with_gateway(int index, const char *gateway, 
const char *host);
 int connman_inet_add_host_route(int index, const char *host);
 int connman_inet_del_host_route(int index, const char *host);
 int connman_inet_set_gateway_address(int index, const char *gateway);
diff --git a/src/connection.c b/src/connection.c
index 154076b..8adad29 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -301,7 +301,7 @@ static int connection_probe(struct connman_element *element)
        }
 
        if (new_gateway->vpn == TRUE) {
-               connman_inet_add_host_route_vpn(active_gateway->index,
+               connman_inet_add_host_route_with_gateway(active_gateway->index,
                                                active_gateway->gateway,
                                                new_gateway->gateway);
        }
diff --git a/src/inet.c b/src/inet.c
index 980bd48..e69cfe4 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -612,13 +612,15 @@ int connman_inet_clear_address(int index)
        return 0;
 }
 
-int connman_inet_add_host_route_vpn(int index, const char *gateway, const char 
*host)
+int connman_inet_add_host_route_with_gateway(int index, const char *gateway, 
const char *host)
 {
        struct ifreq ifr;
        struct rtentry rt;
        struct sockaddr_in addr;
        int sk, err;
 
+       DBG("index %u gateway %s host %s", index, gateway, host);
+
        sk = socket(PF_INET, SOCK_DGRAM, 0);
        if (sk < 0)
                return -1;
@@ -670,6 +672,8 @@ int connman_inet_add_host_route(int index, const char *host)
        struct sockaddr_in addr;
        int sk, err;
 
+       DBG("index %u host %s", index, host);
+
        sk = socket(PF_INET, SOCK_DGRAM, 0);
        if (sk < 0)
                return -1;
diff --git a/src/service.c b/src/service.c
index fd694e8..642bd2f 100644
--- a/src/service.c
+++ b/src/service.c
@@ -298,6 +298,41 @@ static connman_bool_t is_connected(const struct 
connman_service *service)
        return FALSE;
 }
 
+static int add_nameserver_host_route(struct connman_service *service,
+                                               const char *nameserver)
+{
+       int index;
+       const char *gateway;
+
+       index = connman_network_get_index(service->network);
+       gateway = __connman_ipconfig_get_gateway(index);
+       if (gateway != NULL)
+               return connman_inet_add_host_route_with_gateway(index,
+                                               gateway, nameserver);
+       else
+               return connman_inet_add_host_route(index, nameserver);
+}
+
+static int del_nameserver_host_route(struct connman_service *service,
+                                               const char *nameserver)
+{
+       int index;
+       index = connman_network_get_index(service->network);
+       return connman_inet_del_host_route(index, nameserver);
+}
+
+static void del_all_nameserver_host_routes(struct connman_service *service)
+{
+       int i;
+
+       if (service->nameservers != NULL)
+               for (i = 0; service->nameservers[i]; i++)
+                       del_nameserver_host_route(service,
+                                       service->nameservers[i]);
+       else if (service->nameserver != NULL)
+               del_nameserver_host_route(service, service->nameserver);
+}
+
 static void update_nameservers(struct connman_service *service)
 {
        const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
@@ -314,6 +349,7 @@ static void update_nameservers(struct connman_service 
*service)
        case CONNMAN_SERVICE_STATE_FAILURE:
        case CONNMAN_SERVICE_STATE_DISCONNECT:
                connman_resolver_remove_all(ifname);
+               del_all_nameserver_host_routes(service);
                return;
        case CONNMAN_SERVICE_STATE_READY:
        case CONNMAN_SERVICE_STATE_LOGIN:
@@ -322,15 +358,20 @@ static void update_nameservers(struct connman_service 
*service)
        }
 
        connman_resolver_remove_all(ifname);
+       del_all_nameserver_host_routes(service);
 
        if (service->nameservers != NULL) {
                int i;
 
-               for (i = 0; service->nameservers[i]; i++)
+               for (i = 0; service->nameservers[i]; i++) {
+                       add_nameserver_host_route(service, 
service->nameservers[i]);
                        connman_resolver_append(ifname, NULL,
                                                service->nameservers[i]);
-       } else if (service->nameserver != NULL)
+               }
+       } else if (service->nameserver != NULL) {
+               add_nameserver_host_route(service, service->nameserver);
                connman_resolver_append(ifname, NULL, service->nameserver);
+       }
 }
 
 void __connman_service_append_nameserver(struct connman_service *service,
-- 
1.7.0.4

Attachment: signature.asc
Description: Digital signature

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

Reply via email to