+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
+
+ while (service->domains && service->domains[i]) {
+ connman_resolver_remove(index, service->domains[i], NULL);
+ i++;
+ }
+
+ if (service->domainname)
+ connman_resolver_remove(index, service->domainname, NULL);
+
+ return 0;
+}
+
+static int nameserver_add(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ const char *nameserver)
+{
+ int index, ret;
+
+ if (!nameserver_available(service, type, nameserver))
+ return 0;
+
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
+
+ ret = connman_resolver_append(index, NULL, nameserver);
+ if (ret >= 0)
+ nameservers_changed(service);
+
+ return ret;
+}
+
+static int nameserver_add_all(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ int i = 0;
+
+ if (service->nameservers_config) {
+ while (service->nameservers_config[i]) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ i++;
+ }
+ } else if (service->nameservers) {
+ while (service->nameservers[i]) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ i++;
+ }
+ }
+
+ if (!i)
+ __connman_resolver_append_fallback_nameservers();
+
+ searchdomain_add_all(service);
+
+ return 0;
+}
+
+static int nameserver_remove(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ const char *nameserver)
+{
+ int index, ret;
+
+ if (!nameserver_available(service, type, nameserver))
+ return 0;
+
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
+
+ ret = connman_resolver_remove(index, NULL, nameserver);
+ if (ret >= 0)
+ nameservers_changed(service);
+
+ return ret;
+}
+
+static int nameserver_remove_all(struct connman_service *service,
+ enum connman_ipconfig_type type)
+{
+ int index, i = 0;
+
+ index = __connman_service_get_index(service);
+ if (index < 0)
+ return -ENXIO;
+
+ while (service->nameservers_config && service->nameservers_config[i]) {
+
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ i++;
+ }
+
+ i = 0;
+ while (service->nameservers && service->nameservers[i]) {
+ nameserver_remove(service, type, service->nameservers[i]);
+ i++;
+ }
+
+ searchdomain_remove_all(service);
+
+ return 0;
+}
+
+/*
+ * The is_auto variable is set to true when IPv6 autoconf nameservers are
+ * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
+ * for details) and not through service.c
+ */
+int __connman_service_nameserver_append(struct connman_service *service,
+ const char *nameserver, bool is_auto)
+{
+ char **nameservers;
+ int len, i;
+
+ DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
+
+ if (!nameserver)
+ return -EINVAL;
+
+ if (is_auto)
+ nameservers = service->nameservers_auto;
+ else
+ nameservers = service->nameservers;
+
+ if (nameservers) {
+ for (i = 0; nameservers[i]; i++) {
+ if (g_strcmp0(nameservers[i], nameserver) == 0)
+ return -EEXIST;
+ }
+
+ len = g_strv_length(nameservers);
+ nameservers = g_try_renew(char *, nameservers, len + 2);
+ } else {
+ len = 0;
+ nameservers = g_try_new0(char *, len + 2);
+ }
+
+ if (!nameservers)
+ return -ENOMEM;
+
+ nameservers[len] = g_strdup(nameserver);
+ nameservers[len + 1] = NULL;
+
+ if (is_auto) {
+ service->nameservers_auto = nameservers;
+ } else {
+ service->nameservers = nameservers;
+ nameserver_add(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver);
+ }
+
+ nameservers_changed(service);
+
+ searchdomain_add_all(service);
+
+ return 0;
+}
+
+int __connman_service_nameserver_remove(struct connman_service *service,
+ const char *nameserver, bool is_auto)
+{
+ char **servers, **nameservers;
+ bool found = false;
+ int len, i, j;
+
+ DBG("service %p nameserver %s auto %d", service, nameserver, is_auto);
+
+ if (!nameserver)