From: Daniel Wagner <[email protected]>

The current __connman_service_append/remove_nameserver allows only
changing nameserver for the manual (e.g. non DHCP) setup.

__connman_service_append/remove_namerserver() is renamed to
__connman_service_nameserver_append/remove to be more consistent with
the other Service API naming.

Additional the two function take now the type of nameserver (automatic
or manual) and do append or remove the nameserer from the defined list
of nameservers. The previously implementation had a set/clear
semantic.
---
 include/service.h   |    2 +-
 plugins/pacrunner.c |    7 +-
 src/connman.h       |   15 +++-
 src/ipv4.c          |   11 ++-
 src/network.c       |    7 +-
 src/provider.c      |    4 +-
 src/service.c       |  237 ++++++++++++++++++++++++++++++++++++++++-----------
 src/wpad.c          |   11 ++-
 8 files changed, 225 insertions(+), 69 deletions(-)

diff --git a/include/service.h b/include/service.h
index faa6cf8..ad9a494 100644
--- a/include/service.h
+++ b/include/service.h
@@ -104,7 +104,7 @@ enum connman_service_type connman_service_get_type(struct 
connman_service *servi
 char *connman_service_get_interface(struct connman_service *service);
 
 const char *connman_service_get_domainname(struct connman_service *service);
-const char *connman_service_get_nameserver(struct connman_service *service);
+char **connman_service_get_nameservers(struct connman_service *service);
 void connman_service_set_proxy_method(struct connman_service *service, enum 
connman_service_proxy_method method);
 enum connman_service_proxy_method connman_service_get_proxy_method(struct 
connman_service *service);
 char **connman_service_get_proxy_servers(struct connman_service *service);
diff --git a/plugins/pacrunner.c b/plugins/pacrunner.c
index 2d0a419..9e94d60 100644
--- a/plugins/pacrunner.c
+++ b/plugins/pacrunner.c
@@ -168,10 +168,11 @@ static void create_proxy_configuration(void)
                connman_dbus_dict_append_array(&dict, "Domains",
                                        DBUS_TYPE_STRING, append_string, &str);
 
-       str = connman_service_get_nameserver(default_service);
-       if (str != NULL)
+       str_list = connman_service_get_nameservers(default_service);
+       if (str_list != NULL)
                connman_dbus_dict_append_array(&dict, "Nameservers",
-                                       DBUS_TYPE_STRING, append_string, &str);
+                                       DBUS_TYPE_STRING, append_string_list,
+                                       &str_list);
 
        connman_dbus_dict_close(&iter, &dict);
 
diff --git a/src/connman.h b/src/connman.h
index 992d533..b61a626 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -492,10 +492,17 @@ 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);
+enum connman_service_nameserver_type {
+       CONNMAN_SERVICE_NAMESERVER_TYPE_AUTO   = 0,
+       CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL = 1,
+};
+
+int __connman_service_nameserver_append(struct connman_service *service,
+                                       enum connman_service_nameserver_type 
type,
+                                       const char *nameserver);
+int __connman_service_nameserver_remove(struct connman_service *service,
+                                       enum connman_service_nameserver_type 
type,
+                                       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 f6e436c..628a35c 100644
--- a/src/ipv4.c
+++ b/src/ipv4.c
@@ -83,8 +83,11 @@ static int ipv4_probe(struct connman_element *element)
        if (pac != NULL)
                __connman_service_set_proxy_autoconfig(service, pac);
 
-       if (nameserver != NULL)
-               __connman_service_append_nameserver(service, nameserver);
+       if (nameserver != NULL) {
+               __connman_service_nameserver_append(service,
+                                       CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL,
+                                       nameserver);
+       }
 
        connman_timeserver_append(timeserver);
 
@@ -139,7 +142,9 @@ 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,
+                                       CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL,
+                                       nameserver);
        }
 
        prefixlen = __connman_ipconfig_netmask_prefix_len(netmask);
diff --git a/src/network.c b/src/network.c
index 02d7c5c..4832606 100644
--- a/src/network.c
+++ b/src/network.c
@@ -688,8 +688,11 @@ 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);
+       if (nameserver != NULL) {
+               __connman_service_nameserver_append(service,
+                                       CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL,
+                                       nameserver);
+       }
 
        __connman_ipconfig_set_gateway(ipconfig, &network->element);
 
diff --git a/src/provider.c b/src/provider.c
index 6bd2df5..77eae1b 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -297,7 +297,9 @@ 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,
+                               CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL,
+                               value);
        value = second_ns;
 
        while (value) {
diff --git a/src/service.c b/src/service.c
index fa2d3e4..e914197 100644
--- a/src/service.c
+++ b/src/service.c
@@ -84,7 +84,7 @@ struct connman_service {
        struct connman_network *network;
        struct connman_provider *provider;
        char **nameservers;
-       char *nameserver;
+       char **nameservers_manual;
        char **domains;
        char *domainname;
        /* 802.1x settings from the config files */
@@ -308,6 +308,18 @@ static enum connman_service_proxy_method 
string2proxymethod(const char *method)
                return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
 }
 
+static const char *nameservertype2string(enum connman_service_nameserver_type 
type)
+{
+       switch (type) {
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_AUTO:
+               return "automatic";
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL:
+               return "manual";
+       }
+
+       return NULL;
+}
+
 static connman_bool_t is_connecting(struct connman_service *service)
 {
        switch (service->state) {
@@ -381,11 +393,18 @@ static void update_nameservers(struct connman_service 
*service)
        if (service->nameservers != NULL) {
                int i;
 
-               for (i = 0; service->nameservers[i]; 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);
+               }
+       } else if (service->nameservers_manual != NULL) {
+               int i;
+
+               for (i = 0; service->nameservers_manual[i] != NULL; i++) {
+                       connman_resolver_append(ifname, NULL,
+                                               service->nameservers_manual[i]);
+               }
+       }
 
        if (service->domains != NULL) {
                int i;
@@ -399,32 +418,158 @@ static void update_nameservers(struct connman_service 
*service)
        connman_resolver_flush();
 }
 
-void __connman_service_append_nameserver(struct connman_service *service,
+static int nameserver_append(char ***nameservers, const char *nameserver)
+{
+       char **servers;
+       int len;
+
+       servers = *nameservers;
+       if (servers != NULL) {
+               len = g_strv_length(servers);
+               servers = g_try_renew(char *, servers, len + 2);
+       } else {
+               len = 0;
+               servers = g_try_new0(char *, len + 2);
+       }
+
+       if (servers == NULL)
+               return -ENOMEM;
+
+       servers[len] = g_strdup(nameserver);
+       servers[len + 1] = NULL;
+
+       *nameservers = servers;
+
+       return 0;
+}
+
+static int nameserver_remove(char ***nameservers, const char *nameserver)
+{
+       char **servers, **servers_new;
+       int len, i, j;
+
+       servers = *nameservers;
+       if (servers == NULL)
+               return 0;
+
+       len = g_strv_length(servers);
+       if (len == 1) {
+               if (g_strcmp0(servers[0], nameserver) != 0)
+                       return 0;
+
+               g_strfreev(servers);
+               *nameservers = NULL;
+
+               return 0;
+       }
+
+       servers_new = g_try_new0(char *, len - 1);
+       if (servers_new == NULL)
+               return -ENOMEM;
+
+       for (i = 0, j = 0; i < len; i++) {
+               if (g_strcmp0(servers[i], nameserver) != 0) {
+                       servers_new[j] = g_strdup(servers[i]);
+                       j++;
+               }
+       }
+       servers_new[len - 2] = NULL;
+
+       g_strfreev(servers);
+        *nameservers = servers_new;
+
+       return 0;
+}
+
+int __connman_service_nameserver_append(struct connman_service *service,
+                                               enum 
connman_service_nameserver_type type,
                                                const char *nameserver)
 {
-       DBG("service %p nameserver %s", service, nameserver);
+       int err;
+
+       DBG("service %p type %s nameserver %s",
+               service, nameservertype2string(type), nameserver);
 
        if (nameserver == NULL)
-               return;
+               return -EINVAL;
 
-       g_free(service->nameserver);
-       service->nameserver = g_strdup(nameserver);
+       switch (type) {
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_AUTO:
+               err = nameserver_append(&service->nameservers,
+                                       nameserver);
+               if (err < 0)
+                       return err;
+               break;
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL:
+               err = nameserver_append(&service->nameservers_manual,
+                                       nameserver);
+               if (err < 0)
+                       return err;
+               break;
+       }
 
        update_nameservers(service);
+
+       return 0;
 }
 
-void __connman_service_remove_nameserver(struct connman_service *service,
+int __connman_service_nameserver_remove(struct connman_service *service,
+                                               enum 
connman_service_nameserver_type type,
                                                const char *nameserver)
 {
-       DBG("service %p nameserver %s", service, nameserver);
+       int err;
+
+       DBG("service %p type %s nameserver %s",
+               service, nameservertype2string(type), nameserver);
 
        if (nameserver == NULL)
-               return;
+               return -EINVAL;
 
-       g_free(service->nameserver);
-       service->nameserver = NULL;
+       switch (type) {
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_AUTO:
+               err = nameserver_remove(&service->nameservers,
+                                       nameserver);
+               if (err < 0)
+                       return err;
+               break;
+       case CONNMAN_SERVICE_NAMESERVER_TYPE_MANUAL:
+               err = nameserver_remove(&service->nameservers_manual,
+                                       nameserver);
+               if (err < 0)
+                       return err;
+               break;
+       }
 
        update_nameservers(service);
+
+       return 0;
+}
+
+static void nameserver_add_routes(int index, char ***nameservers,
+                                       const char *gw)
+{
+       char **servers;
+       int i;
+
+       servers = *nameservers;
+
+       for (i = 0; servers[i] != NULL; i++) {
+               if (connman_inet_compare_subnet(index, servers[i]))
+                       continue;
+
+               connman_inet_add_host_route(index, servers[i], gw);
+       }
+}
+
+static void nameserver_del_routes(int index, char ***nameservers)
+{
+       char **servers;
+       int i;
+
+       servers = *nameservers;
+
+       for (i = 0; servers[i] != NULL; i++)
+               connman_inet_del_host_route(index, servers[i]);
 }
 
 void __connman_service_nameserver_add_routes(struct connman_service *service,
@@ -438,8 +583,6 @@ void __connman_service_nameserver_add_routes(struct 
connman_service *service,
        index = connman_network_get_index(service->network);
 
        if (service->nameservers != NULL) {
-               int i;
-
                /*
                 * We add nameservers host routes for nameservers that
                 * are not on our subnet. For those who are, the subnet
@@ -447,19 +590,9 @@ 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);
+       } else if (service->nameservers_manual != NULL) {
+               nameserver_add_routes(index, &service->nameservers_manual, gw);
        }
 }
 
@@ -472,15 +605,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 != NULL)
+               nameserver_del_routes(index, &service->nameservers);
+       else if (service->nameservers_manual != NULL)
+               nameserver_del_routes(index, &service->nameservers_manual);
 }
 
 static struct connman_stats *stats_get(struct connman_service *service)
@@ -813,6 +941,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;
@@ -821,20 +962,14 @@ static void append_dns(DBusMessageIter *iter, void 
*user_data)
                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]);
-
+               append_nameserver(iter, &service->nameservers);
                return;
        }
 
-       if (service->nameserver == NULL)
+       if (service->nameservers_manual != NULL) {
+               append_nameserver(iter, &service->nameservers_manual);
                return;
-
-       dbus_message_iter_append_basic(iter,
-                               DBUS_TYPE_STRING, &service->nameserver);
+       }
 }
 
 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
@@ -1546,12 +1681,12 @@ 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;
+       return service->nameservers_manual;
 }
 
 void connman_service_set_proxy_method(struct connman_service *service,
@@ -2645,11 +2780,11 @@ static void service_free(gpointer user_data)
                connman_location_unref(service->location);
 
        g_strfreev(service->nameservers);
+       g_strfreev(service->nameservers_manual);
        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);
diff --git a/src/wpad.c b/src/wpad.c
index 2de8e6e..450a163 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);
 
-- 
1.7.4

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

Reply via email to