5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #define RESOLVER_FLAG_PUBLIC (1 << 0)
39 struct connman_resolver *resolver;
46 static GSList *entry_list = NULL;
47 static GSList *resolver_list = NULL;
49 static void remove_entries(GSList *entries)
53 for (list = entries; list; list = list->next) {
54 struct entry_data *entry = list->data;
55 struct connman_resolver *resolver = entry->resolver;
57 entry_list = g_slist_remove(entry_list, entry);
59 if (resolver && resolver->remove)
60 resolver->remove(entry->interface, entry->domain,
63 g_free(entry->server);
64 g_free(entry->domain);
65 g_free(entry->interface);
69 g_slist_free(entries);
72 static gint compare_priority(gconstpointer a, gconstpointer b)
74 const struct connman_resolver *resolver1 = a;
75 const struct connman_resolver *resolver2 = b;
77 return resolver2->priority - resolver1->priority;
81 * connman_resolver_register:
82 * @resolver: resolver module
84 * Register a new resolver module
86 * Returns: %0 on success
88 int connman_resolver_register(struct connman_resolver *resolver)
92 DBG("resolver %p name %s", resolver, resolver->name);
94 resolver_list = g_slist_insert_sorted(resolver_list, resolver,
97 if (resolver->append == NULL)
100 for (list = entry_list; list; list = list->next) {
101 struct entry_data *entry = list->data;
106 if (resolver->append(entry->interface, entry->domain,
108 entry->resolver = resolver;
115 * connman_resolver_unregister:
116 * @resolver: resolver module
118 * Remove a previously registered resolver module
120 void connman_resolver_unregister(struct connman_resolver *resolver)
122 GSList *list, *matches = NULL;
124 DBG("resolver %p name %s", resolver, resolver->name);
126 resolver_list = g_slist_remove(resolver_list, resolver);
128 for (list = entry_list; list; list = list->next) {
129 struct entry_data *entry = list->data;
131 if (entry->resolver != resolver)
134 matches = g_slist_append(matches, entry);
137 remove_entries(matches);
140 static int append_resolver(const char *interface, const char *domain,
141 const char *server, unsigned int flags)
143 struct entry_data *entry;
146 DBG("interface %s domain %s server %s flags %d",
147 interface, domain, server, flags);
152 entry = g_try_new0(struct entry_data, 1);
156 entry->interface = g_strdup(interface);
157 entry->domain = g_strdup(domain);
158 entry->server = g_strdup(server);
159 entry->flags = flags;
161 entry_list = g_slist_append(entry_list, entry);
163 for (list = resolver_list; list; list = list->next) {
164 struct connman_resolver *resolver = list->data;
166 if (resolver->append == NULL)
169 if (resolver->append(interface, domain, server) == 0) {
170 entry->resolver = resolver;
179 * connman_resolver_append:
180 * @interface: network interface
181 * @domain: domain limitation
182 * @server: server address
184 * Append resolver server address to current list
186 int connman_resolver_append(const char *interface, const char *domain,
189 DBG("interface %s domain %s server %s", interface, domain, server);
191 return append_resolver(interface, domain, server, 0);
195 * connman_resolver_remove:
196 * @interface: network interface
197 * @domain: domain limitation
198 * @server: server address
200 * Remover resolver server address from current list
202 int connman_resolver_remove(const char *interface, const char *domain,
205 GSList *list, *matches = NULL;
207 DBG("interface %s domain %s server %s", interface, domain, server);
212 for (list = entry_list; list; list = list->next) {
213 struct entry_data *entry = list->data;
215 if (interface != NULL &&
216 g_strcmp0(entry->interface, interface) != 0)
219 if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
222 if (g_strcmp0(entry->server, server) != 0)
225 matches = g_slist_append(matches, entry);
231 remove_entries(matches);
237 * connman_resolver_remove_all:
238 * @interface: network interface
240 * Remove all resolver server address for the specified interface
242 int connman_resolver_remove_all(const char *interface)
244 GSList *list, *matches = NULL;
246 DBG("interface %s", interface);
248 if (interface == NULL)
251 for (list = entry_list; list; list = list->next) {
252 struct entry_data *entry = list->data;
254 if (g_strcmp0(entry->interface, interface) != 0)
257 matches = g_slist_append(matches, entry);
263 remove_entries(matches);
269 * connman_resolver_append_public_server:
270 * @server: server address
272 * Append public resolver server address to current list
274 int connman_resolver_append_public_server(const char *server)
276 DBG("server %s", server);
278 return append_resolver(NULL, NULL, server, RESOLVER_FLAG_PUBLIC);
282 * connman_resolver_remove_public_server:
283 * @server: server address
285 * Remove public resolver server address to current list
287 int connman_resolver_remove_public_server(const char *server)
289 DBG("server %s", server);
291 return connman_resolver_remove(NULL, NULL, server);
294 static int selftest_append(const char *interface, const char *domain,
297 DBG("server %s", server);
302 static int selftest_remove(const char *interface, const char *domain,
305 DBG("server %s", server);
310 static struct connman_resolver selftest_resolver = {
312 .priority = CONNMAN_RESOLVER_PRIORITY_HIGH + 42,
313 .append = selftest_append,
314 .remove = selftest_remove,
317 int __connman_resolver_selftest(void)
319 connman_resolver_append("wlan0", "lwn.net", "192.168.0.1");
321 connman_resolver_register(&selftest_resolver);
323 connman_resolver_append("eth0", "moblin.org", "192.168.42.1");
324 connman_resolver_append("wlan0", "lwn.net", "192.168.0.2");
326 connman_resolver_append_public_server("8.8.8.8");
328 connman_resolver_remove_public_server("8.8.8.8");
330 connman_resolver_remove_all("wlan0");
332 connman_resolver_unregister(&selftest_resolver);
337 struct resolvfile_entry {
343 static GList *resolvfile_list = NULL;
345 static void resolvfile_remove_entries(GList *entries)
349 for (list = entries; list; list = list->next) {
350 struct resolvfile_entry *entry = list->data;
352 resolvfile_list = g_list_remove(
353 resolvfile_list, entry);
355 g_free(entry->server);
356 g_free(entry->domain);
357 g_free(entry->interface);
361 g_list_free(entries);
364 static int resolvfile_export(void)
372 content = g_string_new("# Generated by Connection Manager\n"
375 /* Nameservers are added in reverse so that the most recently appended
376 * entry is the primary nameserver. No more than MAXNS nameservers are
379 for (count = 0, list = g_list_last(resolvfile_list);
380 list && (count < MAXNS);
381 list = g_list_previous(list)) {
382 struct resolvfile_entry *entry = list->data;
383 g_string_append_printf(content, "nameserver %s\n",
388 old_umask = umask(022);
390 fd = open("/etc/resolv.conf", O_RDWR | O_CREAT,
391 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
397 if (ftruncate(fd, 0) < 0) {
404 if (write(fd, content->str, content->len) < 0)
411 g_string_free(content, TRUE);
417 static int resolvfile_append(const char *interface, const char *domain,
420 struct resolvfile_entry *entry;
422 DBG("interface %s server %s", interface, server);
424 if (interface == NULL)
427 entry = g_try_new0(struct resolvfile_entry, 1);
431 entry->interface = g_strdup(interface);
432 entry->domain = g_strdup(domain);
433 entry->server = g_strdup(server);
435 resolvfile_list = g_list_append(resolvfile_list, entry);
437 return resolvfile_export();
440 static int resolvfile_remove(const char *interface, const char *domain,
443 GList *list, *matches = NULL;
445 DBG("interface %s server %s", interface, server);
447 for (list = resolvfile_list; list; list = g_list_next(list)) {
448 struct resolvfile_entry *entry = list->data;
450 if (interface != NULL &&
451 g_strcmp0(entry->interface, interface) != 0)
454 if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
457 if (g_strcmp0(entry->server, server) != 0)
460 matches = g_list_append(matches, entry);
463 resolvfile_remove_entries(matches);
465 return resolvfile_export();
468 static struct connman_resolver resolvfile_resolver = {
469 .name = "resolvfile",
470 .priority = CONNMAN_RESOLVER_PRIORITY_LOW,
471 .append = resolvfile_append,
472 .remove = resolvfile_remove,
475 int __connman_resolver_init(void)
479 return connman_resolver_register(&resolvfile_resolver);
482 void __connman_resolver_cleanup(void)
486 connman_resolver_unregister(&resolvfile_resolver);