From: Marcel Holtmann Date: Wed, 12 May 2010 18:13:31 +0000 (+0200) Subject: Add support for setting manual DNS server configuration X-Git-Tag: accepted/2.0alpha-wayland/20121110.002834~2757 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8ef138ed47359f81dd6143a20d39ef249bf75dcd;p=profile%2Fivi%2Fconnman.git Add support for setting manual DNS server configuration --- diff --git a/Makefile.am b/Makefile.am index 64c0264..8a7aca9 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 f3a3050..93f9770 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 int __connman_location_init(void); diff --git a/src/ipv4.c b/src/ipv4.c index fa56078..d3bc846 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, ×erver); 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 31d4004..d5105c3 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 8105f61..e747656 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 f1d7cf1..5657444 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 0000000..9e513a5 --- /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 [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')))