summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/connman.h8
-rw-r--r--src/ipv4.c4
-rw-r--r--src/network.c4
-rw-r--r--src/provider.c2
-rw-r--r--src/service.c216
-rw-r--r--src/wpad.c11
6 files changed, 162 insertions, 83 deletions
diff --git a/src/connman.h b/src/connman.h
index 6202db31..ba1426ee 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -495,10 +495,10 @@ struct connman_service *__connman_service_connect_type(enum connman_service_type
const char *__connman_service_type2string(enum connman_service_type type);
-void __connman_service_append_nameserver(struct connman_service *service,
- const char *nameserver);
-void __connman_service_remove_nameserver(struct connman_service *service,
- const char *nameserver);
+int __connman_service_nameserver_append(struct connman_service *service,
+ const char *nameserver);
+int __connman_service_nameserver_remove(struct connman_service *service,
+ const char *nameserver);
void __connman_service_nameserver_add_routes(struct connman_service *service,
const char *gw);
void __connman_service_nameserver_del_routes(struct connman_service *service);
diff --git a/src/ipv4.c b/src/ipv4.c
index f6e436ce..f7b664bf 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -84,7 +84,7 @@ static int ipv4_probe(struct connman_element *element)
__connman_service_set_proxy_autoconfig(service, pac);
if (nameserver != NULL)
- __connman_service_append_nameserver(service, nameserver);
+ __connman_service_nameserver_append(service, nameserver);
connman_timeserver_append(timeserver);
@@ -139,7 +139,7 @@ static void ipv4_remove(struct connman_element *element)
struct connman_service *service;
service = __connman_element_get_service(element);
- __connman_service_remove_nameserver(service, nameserver);
+ __connman_service_nameserver_remove(service, nameserver);
}
prefixlen = __connman_ipconfig_netmask_prefix_len(netmask);
diff --git a/src/network.c b/src/network.c
index be2cae5b..e0947438 100644
--- a/src/network.c
+++ b/src/network.c
@@ -706,7 +706,7 @@ static void set_connected_manual(struct connman_network *network)
connman_element_get_value(&network->element,
CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
if (nameserver != NULL)
- __connman_service_append_nameserver(service, nameserver);
+ __connman_service_nameserver_append(service, nameserver);
__connman_ipconfig_set_gateway(ipconfig, &network->element);
@@ -790,7 +790,7 @@ static void autoconf_ipv6_set(struct connman_network *network,
connman_element_get_value(&network->element,
CONNMAN_PROPERTY_ID_IPV6_NAMESERVER, &nameserver);
if (nameserver != NULL)
- __connman_service_append_nameserver(service, nameserver);
+ __connman_service_nameserver_append(service, nameserver);
network->connecting = FALSE;
diff --git a/src/provider.c b/src/provider.c
index 150a7ca3..2b9f0f26 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -299,7 +299,7 @@ static void provider_set_nameservers(struct connman_provider *provider)
second_ns = strchr(value, ' ');
if (second_ns)
*(second_ns++) = 0;
- __connman_service_append_nameserver(service, value);
+ __connman_service_nameserver_append(service, value);
value = second_ns;
while (value) {
diff --git a/src/service.c b/src/service.c
index 7751dc07..9a20aee1 100644
--- a/src/service.c
+++ b/src/service.c
@@ -85,7 +85,7 @@ struct connman_service {
struct connman_network *network;
struct connman_provider *provider;
char **nameservers;
- char *nameserver;
+ char **nameservers_config;
char **domains;
char *domainname;
/* 802.1x settings from the config files */
@@ -514,14 +514,21 @@ static void update_nameservers(struct connman_service *service)
connman_resolver_remove_all(ifname);
- if (service->nameservers != NULL) {
+ if (service->nameservers_config != NULL) {
int i;
- for (i = 0; service->nameservers[i]; i++)
+ for (i = 0; service->nameservers_config[i] != NULL; i++) {
+ connman_resolver_append(ifname, NULL,
+ service->nameservers_config[i]);
+ }
+ } else if (service->nameservers != NULL) {
+ int i;
+
+ for (i = 0; service->nameservers[i] != NULL; i++) {
connman_resolver_append(ifname, NULL,
service->nameservers[i]);
- } else if (service->nameserver != NULL)
- connman_resolver_append(ifname, NULL, service->nameserver);
+ }
+ }
if (service->domains != NULL) {
int i;
@@ -535,32 +542,100 @@ static void update_nameservers(struct connman_service *service)
connman_resolver_flush();
}
-void __connman_service_append_nameserver(struct connman_service *service,
+int __connman_service_nameserver_append(struct connman_service *service,
const char *nameserver)
{
- DBG("service %p nameserver %s", service, nameserver);
+ int len;
+
+ DBG("service %p nameserver %s", service, nameserver);
if (nameserver == NULL)
- return;
+ return -EINVAL;
- g_free(service->nameserver);
- service->nameserver = g_strdup(nameserver);
+ if (service->nameservers != NULL) {
+ len = g_strv_length(service->nameservers);
+ service->nameservers = g_try_renew(char *, service->nameservers,
+ len + 2);
+ } else {
+ len = 0;
+ service->nameservers = g_try_new0(char *, len + 2);
+ }
+
+ if (service->nameservers == NULL)
+ return -ENOMEM;
+
+ service->nameservers[len] = g_strdup(nameserver);
+ service->nameservers[len + 1] = NULL;
update_nameservers(service);
+
+ return 0;
}
-void __connman_service_remove_nameserver(struct connman_service *service,
+int __connman_service_nameserver_remove(struct connman_service *service,
const char *nameserver)
{
+ char **servers;
+ int len, i, j;
+
DBG("service %p nameserver %s", service, nameserver);
if (nameserver == NULL)
- return;
+ return -EINVAL;
- g_free(service->nameserver);
- service->nameserver = NULL;
+ if (service->nameservers == NULL)
+ return 0;
+
+ len = g_strv_length(service->nameservers);
+ if (len == 1) {
+ if (g_strcmp0(service->nameservers[0], nameserver) != 0)
+ return 0;
+
+ g_strfreev(service->nameservers);
+ service->nameservers = NULL;
+
+ return 0;
+ }
+
+ servers = g_try_new0(char *, len - 1);
+ if (servers == NULL)
+ return -ENOMEM;
+
+ for (i = 0, j = 0; i < len; i++) {
+ if (g_strcmp0(service->nameservers[i], nameserver) != 0) {
+ servers[j] = g_strdup(service->nameservers[i]);
+ j++;
+ }
+ }
+ servers[len - 2] = NULL;
+
+ g_strfreev(service->nameservers);
+ service->nameservers = servers;
update_nameservers(service);
+
+ return 0;
+}
+
+static void nameserver_add_routes(int index, char **nameservers,
+ const char *gw)
+{
+ int i;
+
+ for (i = 0; nameservers[i] != NULL; i++) {
+ if (connman_inet_compare_subnet(index, nameservers[i]))
+ continue;
+
+ connman_inet_add_host_route(index, nameservers[i], gw);
+ }
+}
+
+static void nameserver_del_routes(int index, char **nameservers)
+{
+ int i;
+
+ for (i = 0; nameservers[i] != NULL; i++)
+ connman_inet_del_host_route(index, nameservers[i]);
}
void __connman_service_nameserver_add_routes(struct connman_service *service,
@@ -573,9 +648,13 @@ void __connman_service_nameserver_add_routes(struct connman_service *service,
index = connman_network_get_index(service->network);
- if (service->nameservers != NULL) {
- int i;
-
+ if (service->nameservers_config != NULL) {
+ /*
+ * Configured nameserver takes preference over the
+ * discoverd nameserver gathered from DHCP, VPN, etc.
+ */
+ nameserver_add_routes(index, service->nameservers_config, gw);
+ } else if (service->nameservers != NULL) {
/*
* We add nameservers host routes for nameservers that
* are not on our subnet. For those who are, the subnet
@@ -583,19 +662,7 @@ void __connman_service_nameserver_add_routes(struct connman_service *service,
* tries to reach them. The subnet route is installed
* when setting the interface IP address.
*/
- for (i = 0; service->nameservers[i]; i++) {
- if (connman_inet_compare_subnet(index,
- service->nameservers[i]))
- continue;
-
- connman_inet_add_host_route(index,
- service->nameservers[i], gw);
- }
- } else if (service->nameserver != NULL) {
- if (connman_inet_compare_subnet(index, service->nameserver))
- return;
-
- connman_inet_add_host_route(index, service->nameserver, gw);
+ nameserver_add_routes(index, service->nameservers, gw);
}
}
@@ -608,15 +675,10 @@ void __connman_service_nameserver_del_routes(struct connman_service *service)
index = connman_network_get_index(service->network);
- if (service->nameservers != NULL) {
- int i;
-
- for (i = 0; service->nameservers[i]; i++)
- connman_inet_del_host_route(index,
- service->nameservers[i]);
- } else if (service->nameserver != NULL) {
- connman_inet_del_host_route(index, service->nameserver);
- }
+ if (service->nameservers_config != NULL)
+ nameserver_del_routes(index, service->nameservers_config);
+ else if (service->nameservers != NULL)
+ nameserver_del_routes(index, service->nameservers);
}
static struct connman_stats *stats_get(struct connman_service *service)
@@ -972,6 +1034,19 @@ static void append_ipv6config(DBusMessageIter *iter, void *user_data)
iter);
}
+static void append_nameserver(DBusMessageIter *iter, char ***nameservers)
+{
+ char **servers;
+ int i;
+
+ servers = *nameservers;
+
+ for (i = 0; servers[i] != NULL; i++) {
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &servers[i]);
+ }
+}
+
static void append_dns(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
@@ -979,21 +1054,13 @@ static void append_dns(DBusMessageIter *iter, void *user_data)
if (is_connected(service) == FALSE)
return;
- if (service->nameservers != NULL) {
- int i;
-
- for (i = 0; service->nameservers[i]; i++)
- dbus_message_iter_append_basic(iter,
- DBUS_TYPE_STRING, &service->nameservers[i]);
-
+ if (service->nameservers_config != NULL) {
+ append_nameserver(iter, &service->nameservers_config);
return;
- }
-
- if (service->nameserver == NULL)
+ } else if (service->nameservers != NULL) {
+ append_nameserver(iter, &service->nameservers);
return;
-
- dbus_message_iter_append_basic(iter,
- DBUS_TYPE_STRING, &service->nameserver);
+ }
}
static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
@@ -1001,12 +1068,14 @@ static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
struct connman_service *service = user_data;
int i;
- if (service->nameservers == NULL)
+ if (service->nameservers_config == NULL)
return;
- for (i = 0; service->nameservers[i]; i++)
+ for (i = 0; service->nameservers_config[i]; i++) {
dbus_message_iter_append_basic(iter,
- DBUS_TYPE_STRING, &service->nameservers[i]);
+ DBUS_TYPE_STRING,
+ &service->nameservers_config[i]);
+ }
}
static void append_domain(DBusMessageIter *iter, void *user_data)
@@ -1703,12 +1772,17 @@ const char *connman_service_get_domainname(struct connman_service *service)
return service->domainname;
}
-const char *connman_service_get_nameserver(struct connman_service *service)
+char **connman_service_get_nameservers(struct connman_service *service)
{
if (service == NULL)
return NULL;
- return service->nameserver;
+ if (service->nameservers_config != NULL)
+ return service->nameservers_config;
+ else if (service->nameservers != NULL)
+ return service->nameservers;
+
+ return NULL;
}
void connman_service_set_proxy_method(struct connman_service *service,
@@ -2204,12 +2278,14 @@ static DBusMessage *set_property(DBusConnection *conn,
g_string_append(str, val);
}
- g_strfreev(service->nameservers);
+ g_strfreev(service->nameservers_config);
- if (str->len > 0)
- service->nameservers = g_strsplit_set(str->str, " ", 0);
- else
- service->nameservers = NULL;
+ if (str->len > 0) {
+ service->nameservers_config =
+ g_strsplit_set(str->str, " ", 0);
+ } else {
+ service->nameservers_config = NULL;
+ }
g_string_free(str, TRUE);
@@ -2848,11 +2924,11 @@ static void service_free(gpointer user_data)
connman_location_unref(service->location);
g_strfreev(service->nameservers);
+ g_strfreev(service->nameservers_config);
g_strfreev(service->domains);
g_strfreev(service->proxies);
g_strfreev(service->excludes);
- g_free(service->nameserver);
g_free(service->domainname);
g_free(service->pac);
g_free(service->mcc);
@@ -4929,11 +5005,11 @@ static int service_load(struct connman_service *service)
__connman_ipconfig_load(service->ipconfig_ipv6, keyfile,
service->identifier, "IPv6.");
- service->nameservers = g_key_file_get_string_list(keyfile,
+ service->nameservers_config = g_key_file_get_string_list(keyfile,
service->identifier, "Nameservers", &length, NULL);
- if (service->nameservers != NULL && length == 0) {
- g_strfreev(service->nameservers);
- service->nameservers = NULL;
+ if (service->nameservers_config != NULL && length == 0) {
+ g_strfreev(service->nameservers_config);
+ service->nameservers_config = NULL;
}
service->domains = g_key_file_get_string_list(keyfile,
@@ -5111,12 +5187,12 @@ update:
__connman_ipconfig_save(service->ipconfig_ipv6, keyfile,
service->identifier, "IPv6.");
- if (service->nameservers != NULL) {
- guint len = g_strv_length(service->nameservers);
+ if (service->nameservers_config != NULL) {
+ guint len = g_strv_length(service->nameservers_config);
g_key_file_set_string_list(keyfile, service->identifier,
"Nameservers",
- (const gchar **) service->nameservers, len);
+ (const gchar **) service->nameservers_config, len);
} else
g_key_file_remove_key(keyfile, service->identifier,
"Nameservers", NULL);
diff --git a/src/wpad.c b/src/wpad.c
index 2de8e6eb..450a1634 100644
--- a/src/wpad.c
+++ b/src/wpad.c
@@ -117,8 +117,10 @@ failed:
int __connman_wpad_start(struct connman_service *service)
{
struct connman_wpad *wpad;
- const char *domainname, *nameserver;
+ const char *domainname;
+ char **nameservers;
int index;
+ int i;
DBG("service %p", service);
@@ -133,8 +135,8 @@ int __connman_wpad_start(struct connman_service *service)
if (domainname == NULL)
return -EINVAL;
- nameserver = connman_service_get_nameserver(service);
- if (nameserver == NULL)
+ nameservers = connman_service_get_nameservers(service);
+ if (nameservers == NULL)
return -EINVAL;
wpad = g_try_new0(struct connman_wpad, 1);
@@ -151,7 +153,8 @@ int __connman_wpad_start(struct connman_service *service)
if (getenv("CONNMAN_RESOLV_DEBUG"))
g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV");
- g_resolv_add_nameserver(wpad->resolv, nameserver, 53, 0);
+ for (i = 0; nameservers[i] != NULL; i++)
+ g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0);
wpad->hostname = g_strdup_printf("wpad.%s", domainname);