[RFC][PATCH] resolvfile: Support multiple nameservers.

Forest Bond forest at alittletooquiet.net
Wed Apr 21 07:45:20 PDT 2010


I'm trying to take an incremental approach to the resolver changes I've
proposed.  I suspect the only possibly controversial thing I've suggested are
changes to connman_element.  Can anyone comment?


Nameservers are appended to a local entry list.  The MAXNS most recently
appended nameservers written to /etc/resolv.conf.
---
 src/resolver.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 99 insertions(+), 14 deletions(-)

diff --git a/src/resolver.c b/src/resolver.c
index df0d3c1..2d5b3cc 100644
--- a/src/resolver.c
+++ b/src/resolver.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <resolv.h>
 
 #include "connman.h"
 
@@ -333,17 +334,63 @@ int __connman_resolver_selftest(void)
 	return 0;
 }
 
-static int resolvfile_append(const char *interface, const char *domain,
-							const char *server)
-{
+struct resolvfile_entry_data {
+	char *interface;
+	char *domain;
+	char *server;
+};
+
+static GSList *resolvfile_entry_list = NULL;
+
+static void resolvfile_remove_entries(GSList *entries) {
+	GSList *list;
+
+	for (list = entries; list; list = list->next) {
+		struct resolvfile_entry_data *entry = list->data;
+
+		resolvfile_entry_list = g_slist_remove(
+					resolvfile_entry_list, entry);
+
+		g_free(entry->server);
+		g_free(entry->domain);
+		g_free(entry->interface);
+		g_free(entry);
+	}
+
+	g_slist_free(entries);
+}
+
+static int resolvfile_export(void) {
+	GSList *list;
 	char *cmd;
-	int fd, len, err;
+	char **nameservers;
+	char *nameservers_text;
+	int index, n, fd, len, err;
 	mode_t old_umask;
 
-	DBG("interface %s server %s", interface, server);
+	nameservers = g_try_new0(char *, MAXNS + 1);
 
-	if (interface == NULL)
-		return -ENOENT;
+	n = g_slist_length(resolvfile_entry_list) - MAXNS;
+	if (n < 0)
+		n = 0;
+
+	index = 0;
+	for(list = g_slist_nth(resolvfile_entry_list, n); list != NULL;
+						list = g_slist_next(list)) {
+		struct resolvfile_entry_data *entry = list->data;
+		nameservers[index] = g_strdup_printf(
+					"nameserver %s", entry->server);
+		index++;
+	}
+	nameservers[index] = NULL;
+
+	nameservers_text = g_strjoinv("\n", nameservers);
+	g_strfreev(nameservers);
+
+	cmd = g_strdup_printf("# Generated by Connection Manager\n"
+						"options edns0\n"
+						"%s\n", nameservers_text);
+	g_free(nameservers_text);
 
 	old_umask = umask(022);
 
@@ -361,31 +408,69 @@ static int resolvfile_append(const char *interface, const char *domain,
 
 	err = 0;
 
-	cmd = g_strdup_printf("# Generated by Connection Manager\n"
-						"options edns0\n"
-						"nameserver %s\n", server);
-
 	len = write(fd, cmd, strlen(cmd));
 	if (len < 0)
 		err = -errno;
 
-	g_free(cmd);
-
 failed:
 	close(fd);
 
 done:
+	g_free(cmd);
 	umask(old_umask);
 
 	return err;
 }
 
+static int resolvfile_append(const char *interface, const char *domain,
+							const char *server)
+{
+	struct resolvfile_entry_data *entry;
+
+	DBG("interface %s server %s", interface, server);
+
+	if (interface == NULL)
+		return -ENOENT;
+
+	entry = g_try_new0(struct resolvfile_entry_data, 1);
+	if (entry == NULL)
+		return -ENOMEM;
+
+	entry->interface = g_strdup(interface);
+	entry->domain = g_strdup(domain);
+	entry->server = g_strdup(server);
+
+	resolvfile_entry_list = g_slist_append(resolvfile_entry_list, entry);
+
+	return resolvfile_export();
+}
+
 static int resolvfile_remove(const char *interface, const char *domain,
 							const char *server)
 {
+	GSList *list, *matches = NULL;
+
 	DBG("interface %s server %s", interface, server);
 
-	return 0;
+	for (list = resolvfile_entry_list; list; list = g_slist_next(list)) {
+		struct resolvfile_entry_data *entry = list->data;
+
+		if (interface != NULL &&
+				g_strcmp0(entry->interface, interface) != 0)
+			continue;
+
+		if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
+			continue;
+
+		if (g_strcmp0(entry->server, server) != 0)
+			continue;
+
+		matches = g_slist_append(matches, entry);
+	}
+
+	resolvfile_remove_entries(matches);
+
+	return resolvfile_export();
 }
 
 static struct connman_resolver resolvfile_resolver = {
-- 
1.6.0.4
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.01.org/pipermail/connman/attachments/20100421/f170be13/attachment.asc>


More information about the connman mailing list