summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--src/connman.h5
-rw-r--r--src/ipv4.c30
-rw-r--r--src/service.c193
-rwxr-xr-xtest/list-services9
-rwxr-xr-xtest/monitor-services9
-rwxr-xr-xtest/set-nameservers20
7 files changed, 254 insertions, 15 deletions
diff --git a/Makefile.am b/Makefile.am
index 64c02644..8a7aca93 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -142,7 +142,8 @@ test_scripts = test/get-state test/list-profiles test/list-services \
test/simple-agent test/show-introspection test/test-compat \
test/test-manager test/test-connman test/monitor-connman \
test/connect-vpn test/disconnect-vpn test/list-providers \
- test/monitor-manager test/test-counter test/set-ip-method
+ test/monitor-manager test/test-counter test/set-ip-method \
+ test/set-nameservers
if TEST
testdir = $(pkglibdir)/test
diff --git a/src/connman.h b/src/connman.h
index f3a3050d..93f97708 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -420,6 +420,11 @@ 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);
+
#include <connman/location.h>
int __connman_location_init(void);
diff --git a/src/ipv4.c b/src/ipv4.c
index fa560788..d3bc8461 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -40,8 +40,7 @@ struct connman_ipv4 {
struct in_addr broadcast;
};
-static int set_ipv4(struct connman_element *element,
- struct connman_ipv4 *ipv4, const char *nameserver)
+static int set_ipv4(struct connman_element *element, struct connman_ipv4 *ipv4)
{
struct ifreq ifr;
struct sockaddr_in addr;
@@ -95,11 +94,6 @@ static int set_ipv4(struct connman_element *element,
close(sk);
- if (nameserver == NULL)
- connman_error("No nameserver for %s defined", ifr.ifr_name);
- else
- connman_resolver_append(ifr.ifr_name, NULL, nameserver);
-
return 0;
}
@@ -125,8 +119,6 @@ static int clear_ipv4(struct connman_element *element)
DBG("ifname %s", ifr.ifr_name);
- connman_resolver_remove_all(ifr.ifr_name);
-
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
@@ -207,7 +199,14 @@ static int ipv4_probe(struct connman_element *element)
ipv4.broadcast.s_addr = ipv4.address.s_addr |
~ipv4.netmask.s_addr;
- set_ipv4(element, &ipv4, nameserver);
+ set_ipv4(element, &ipv4);
+
+ if (nameserver != NULL) {
+ struct connman_service *service;
+
+ service = __connman_element_get_service(element);
+ __connman_service_append_nameserver(service, nameserver);
+ }
connman_timeserver_append(timeserver);
@@ -225,15 +224,24 @@ static int ipv4_probe(struct connman_element *element)
static void ipv4_remove(struct connman_element *element)
{
- const char *timeserver = NULL;
+ const char *nameserver = NULL, *timeserver = NULL;
DBG("element %p name %s", element, element->name);
connman_element_get_value(element,
+ CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
+ connman_element_get_value(element,
CONNMAN_PROPERTY_ID_IPV4_TIMESERVER, &timeserver);
connman_timeserver_remove(timeserver);
+ if (nameserver != NULL) {
+ struct connman_service *service;
+
+ service = __connman_element_get_service(element);
+ __connman_service_remove_nameserver(service, nameserver);
+ }
+
clear_ipv4(element);
}
diff --git a/src/service.c b/src/service.c
index 31d4004a..d5105c30 100644
--- a/src/service.c
+++ b/src/service.c
@@ -65,6 +65,8 @@ struct connman_service {
connman_bool_t roaming;
struct connman_ipconfig *ipconfig;
struct connman_network *network;
+ char **nameservers;
+ char *nameserver;
/* 802.1x settings from the config files */
char *eap;
char *identity;
@@ -283,6 +285,69 @@ static connman_bool_t is_connected(const struct connman_service *service)
return FALSE;
}
+static void update_nameservers(struct connman_service *service)
+{
+ const char *ifname = connman_ipconfig_get_ifname(service->ipconfig);
+
+ if (ifname == NULL)
+ return;
+
+ switch (service->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ return;
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ connman_resolver_remove_all(ifname);
+ return;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_LOGIN:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ break;
+ }
+
+ connman_resolver_remove_all(ifname);
+
+ if (service->nameservers != NULL) {
+ int i;
+
+ for (i = 0; service->nameservers[i]; i++)
+ connman_resolver_append(ifname, NULL,
+ service->nameservers[i]);
+ } else if (service->nameserver != NULL)
+ connman_resolver_append(ifname, NULL, service->nameserver);
+}
+
+void __connman_service_append_nameserver(struct connman_service *service,
+ const char *nameserver)
+{
+ DBG("service %p nameserver %s", service, nameserver);
+
+ if (nameserver == NULL)
+ return;
+
+ g_free(service->nameserver);
+ service->nameserver = g_strdup(nameserver);
+
+ update_nameservers(service);
+}
+
+void __connman_service_remove_nameserver(struct connman_service *service,
+ const char *nameserver)
+{
+ DBG("service %p nameserver %s", service, nameserver);
+
+ if (nameserver == NULL)
+ return;
+
+ g_free(service->nameserver);
+ service->nameserver = NULL;
+
+ update_nameservers(service);
+}
+
static struct connman_service *get_default(void)
{
struct connman_service *service;
@@ -490,6 +555,43 @@ static void append_ipv4config(DBusMessageIter *iter, void *user_data)
__connman_ipconfig_append_ipv4config(service->ipconfig, iter);
}
+static void append_dns(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = 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]);
+
+ return;
+ }
+
+ if (service->nameserver == NULL)
+ return;
+
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->nameserver);
+}
+
+static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
+{
+ struct connman_service *service = user_data;
+ int i;
+
+ if (service->nameservers == NULL)
+ return;
+
+ for (i = 0; service->nameservers[i]; i++)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &service->nameservers[i]);
+}
+
static void append_proxy(DBusMessageIter *iter, void *user_data)
{
struct connman_service *service = user_data;
@@ -517,6 +619,26 @@ static void ipv4_configuration_changed(struct connman_service *service)
service);
}
+static void dns_changed(struct connman_service *service)
+{
+ if (is_connected(service) == FALSE)
+ return;
+
+ connman_dbus_property_changed_array(service->path,
+ CONNMAN_SERVICE_INTERFACE, "Nameservers",
+ DBUS_TYPE_STRING, append_dns, service);
+}
+
+static void dns_configuration_changed(struct connman_service *service)
+{
+ connman_dbus_property_changed_array(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "Nameservers.Configuration",
+ DBUS_TYPE_STRING, append_dnsconfig, service);
+
+ dns_changed(service);
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -662,6 +784,12 @@ static DBusMessage *get_properties(DBusConnection *conn,
connman_dbus_dict_append_dict(&dict, "IPv4.Configuration",
append_ipv4config, service);
+ connman_dbus_dict_append_array(&dict, "Nameservers",
+ DBUS_TYPE_STRING, append_dns, service);
+
+ connman_dbus_dict_append_array(&dict, "Nameservers.Configuration",
+ DBUS_TYPE_STRING, append_dnsconfig, service);
+
connman_dbus_dict_append_dict(&dict, "Proxy", append_proxy, service);
connman_dbus_dict_close(&array, &dict);
@@ -792,6 +920,42 @@ static DBusMessage *set_property(DBusConnection *conn,
"Cellular.Password", service->password);
__connman_storage_save_service(service);
+ } else if (g_str_equal(name, "Nameservers.Configuration") == TRUE) {
+ DBusMessageIter entry;
+ GString *str;
+
+ if (type != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ str = g_string_new(NULL);
+ if (str == NULL)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&value, &entry);
+
+ while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+ const char *val;
+ dbus_message_iter_get_basic(&entry, &val);
+ dbus_message_iter_next(&entry);
+ if (str->len > 0)
+ g_string_append_printf(str, " %s", val);
+ else
+ g_string_append(str, val);
+ }
+
+ g_strfreev(service->nameservers);
+
+ if (str->len > 0)
+ service->nameservers = g_strsplit_set(str->str, " ", 0);
+ else
+ service->nameservers = NULL;
+
+ g_string_free(str, TRUE);
+
+ update_nameservers(service);
+ dns_configuration_changed(service);
+
+ __connman_storage_save_service(service);
} else if (g_str_equal(name, "IPv4.Configuration") == TRUE) {
int err;
@@ -1282,6 +1446,8 @@ static void service_free(gpointer user_data)
if (service->location != NULL)
connman_location_unref(service->location);
+ g_strfreev(service->nameservers);
+
g_free(service->mcc);
g_free(service->mnc);
g_free(service->apn);
@@ -1496,8 +1662,7 @@ __connman_service_get_network(struct connman_service *service)
return service->network;
}
-struct connman_ipconfig *
-__connman_service_get_ipconfig(struct connman_service *service)
+struct connman_ipconfig *__connman_service_get_ipconfig(struct connman_service *service)
{
if (service == NULL)
return NULL;
@@ -1632,15 +1797,20 @@ int __connman_service_indicate_state(struct connman_service *service,
g_get_current_time(&service->modified);
__connman_storage_save_service(service);
+ update_nameservers(service);
+ dns_changed(service);
+
__connman_notifier_connect(service->type);
default_changed();
-
} else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
__connman_location_finish(service);
default_changed();
+ update_nameservers(service);
+ dns_changed(service);
+
__connman_notifier_disconnect(service->type);
}
@@ -2733,6 +2903,13 @@ static int service_load(struct connman_service *service)
__connman_ipconfig_load(service->ipconfig, keyfile,
service->identifier, "IPv4.");
+ service->nameservers = 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;
+ }
+
done:
g_key_file_free(keyfile);
@@ -2866,6 +3043,16 @@ update:
__connman_ipconfig_save(service->ipconfig, keyfile,
service->identifier, "IPv4.");
+ if (service->nameservers != NULL) {
+ guint len = g_strv_length(service->nameservers);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "Nameservers",
+ (const gchar **) service->nameservers, len);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Nameservers", NULL);
+
data = g_key_file_to_data(keyfile, &length, NULL);
if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
diff --git a/test/list-services b/test/list-services
index 8105f61c..e7476561 100755
--- a/test/list-services
+++ b/test/list-services
@@ -10,6 +10,13 @@ def extract_values(values):
val += " }"
return val
+def extract_list(list):
+ val = "["
+ for i in list:
+ val += " " + str(i)
+ val += " ]"
+ return val
+
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.moblin.connman", "/"),
@@ -28,6 +35,8 @@ for path in properties["Services"]:
for key in properties.keys():
if key in ["IPv4", "IPv4.Configuration", "Proxy", "Ethernet"]:
val = extract_values(properties[key])
+ elif key in ["Nameservers", "Nameservers.Configuration"]:
+ val = extract_list(properties[key])
elif key in ["Favorite", "Immutable", "AutoConnect",
"SetupRequired", "PassphraseRequired"]:
if properties[key] == dbus.Boolean(1):
diff --git a/test/monitor-services b/test/monitor-services
index f1d7cf1c..5657444c 100755
--- a/test/monitor-services
+++ b/test/monitor-services
@@ -13,6 +13,13 @@ def extract_values(values):
val += " }"
return val
+def extract_list(list):
+ val = "["
+ for i in list:
+ val += " " + str(i)
+ val += " ]"
+ return val
+
def property_changed(name, value, path):
service = path[path.rfind("/") + 1:]
if name in ["Profiles", "Services", "Providers", "Technologies",
@@ -23,6 +30,8 @@ def property_changed(name, value, path):
val = val + " ]"
elif name in ["IPv4", "IPv4.Configuration", "Proxy", "Ethernet"]:
val = extract_values(value)
+ elif name in ["Nameservers", "Nameservers.Configuration"]:
+ val = extract_list(value)
elif name in ["Strength", "Priority"]:
val = int(value)
else:
diff --git a/test/set-nameservers b/test/set-nameservers
new file mode 100755
index 00000000..9e513a5b
--- /dev/null
+++ b/test/set-nameservers
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+
+import sys
+import dbus
+
+if (len(sys.argv) < 2):
+ print "Usage: %s <service> [nameserver*]" % (sys.argv[0])
+ sys.exit(1)
+
+bus = dbus.SystemBus()
+path = "/profile/default/" + sys.argv[1]
+service = dbus.Interface(bus.get_object('org.moblin.connman', path),
+ 'org.moblin.connman.Service')
+
+properties = service.GetProperties()
+
+print "Setting nameserver to %s" % (sys.argv[2:])
+
+service.SetProperty("Nameservers.Configuration",
+ dbus.Array(sys.argv[2:], signature=dbus.Signature('s')))