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 | 3 +-
src/connman.h | 3 ++
src/inet.c | 6 ++++-
src/service.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 65 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..5546a82 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -277,6 +277,7 @@ static int connection_probe(struct connman_element *element)
}
service = __connman_element_get_service(element);
+ __connman_service_set_gateway(service, gateway);
__connman_service_indicate_state(service,
CONNMAN_SERVICE_STATE_READY);
@@ -301,7 +302,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/connman.h b/src/connman.h
index 1fdada3..dc246b3 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -440,6 +440,9 @@ void __connman_service_append_nameserver(struct
connman_service *service,
void __connman_service_remove_nameserver(struct connman_service *service,
const char *nameserver);
+void __connman_service_set_gateway(struct connman_service *service,
+ const char *gateway);
+
unsigned long __connman_service_stats_get_tx_bytes(struct connman_service
*service);
unsigned long __connman_service_stats_get_rx_bytes(struct connman_service
*service);
unsigned long __connman_service_stats_get_time(struct connman_service
*service);
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..fed9ff5 100644
--- a/src/service.c
+++ b/src/service.c
@@ -78,6 +78,7 @@ struct connman_service {
struct connman_network *network;
char **nameservers;
char *nameserver;
+ char *gateway;
char **domains;
/* 802.1x settings from the config files */
char *eap;
@@ -298,6 +299,39 @@ 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;
+
+ index = connman_network_get_index(service->network);
+ if (service->gateway != NULL)
+ return connman_inet_add_host_route_with_gateway(index,
+ service->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 +348,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 +357,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,
@@ -361,6 +401,18 @@ void __connman_service_remove_nameserver(struct
connman_service *service,
update_nameservers(service);
}
+void __connman_service_set_gateway(struct connman_service *service,
+ const char *gateway)
+{
+ if (service == NULL)
+ return;
+
+ if (service->gateway != NULL)
+ g_free(service->gateway);
+
+ service->gateway = g_strdup(gateway);
+}
+
static void __connman_service_stats_start(struct connman_service *service)
{
DBG("service %p", service);
--
1.7.0.4
signature.asc
Description: Digital signature
_______________________________________________ connman mailing list [email protected] http://lists.connman.net/listinfo/connman
