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);
295 * connman_resolver_flush:
297 * Flush pending resolver requests
299 void connman_resolver_flush(void)
303 for (list = resolver_list; list; list = list->next) {
304 struct connman_resolver *resolver = list->data;
306 if (resolver->flush == NULL)
315 struct resolvfile_entry {
321 static GList *resolvfile_list = NULL;
323 static void resolvfile_remove_entries(GList *entries)
327 for (list = entries; list; list = list->next) {
328 struct resolvfile_entry *entry = list->data;
330 resolvfile_list = g_list_remove(resolvfile_list, entry);
332 g_free(entry->server);
333 g_free(entry->domain);
334 g_free(entry->interface);
338 g_list_free(entries);
341 static int resolvfile_export(void)
349 content = g_string_new("# Generated by Connection Manager\n");
352 * Nameservers are added in reverse so that the most recently
353 * appended entry is the primary nameserver. No more than MAXNS
354 * nameservers are used.
356 for (count = 0, list = g_list_last(resolvfile_list);
357 list && (count < MAXNS);
358 list = g_list_previous(list)) {
359 struct resolvfile_entry *entry = list->data;
360 g_string_append_printf(content, "nameserver %s\n",
365 old_umask = umask(022);
367 fd = open("/etc/resolv.conf", O_RDWR | O_CREAT,
368 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
374 if (ftruncate(fd, 0) < 0) {
381 if (write(fd, content->str, content->len) < 0)
388 g_string_free(content, TRUE);
394 static int resolvfile_append(const char *interface, const char *domain,
397 struct resolvfile_entry *entry;
399 DBG("interface %s server %s", interface, server);
401 if (interface == NULL)
404 entry = g_try_new0(struct resolvfile_entry, 1);
408 entry->interface = g_strdup(interface);
409 entry->domain = g_strdup(domain);
410 entry->server = g_strdup(server);
412 resolvfile_list = g_list_append(resolvfile_list, entry);
414 return resolvfile_export();
417 static int resolvfile_remove(const char *interface, const char *domain,
420 GList *list, *matches = NULL;
422 DBG("interface %s server %s", interface, server);
424 for (list = resolvfile_list; list; list = g_list_next(list)) {
425 struct resolvfile_entry *entry = list->data;
427 if (interface != NULL &&
428 g_strcmp0(entry->interface, interface) != 0)
431 if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
434 if (g_strcmp0(entry->server, server) != 0)
437 matches = g_list_append(matches, entry);
440 resolvfile_remove_entries(matches);
442 return resolvfile_export();
445 static struct connman_resolver resolvfile_resolver = {
446 .name = "resolvfile",
447 .priority = CONNMAN_RESOLVER_PRIORITY_LOW,
448 .append = resolvfile_append,
449 .remove = resolvfile_remove,
452 int __connman_resolver_init(void)
456 return connman_resolver_register(&resolvfile_resolver);
459 void __connman_resolver_cleanup(void)
463 connman_resolver_unregister(&resolvfile_resolver);