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)
46 static GSList *entry_list = NULL;
47 static connman_bool_t dnsproxy_enabled = FALSE;
49 struct resolvfile_entry {
55 static GList *resolvfile_list = NULL;
57 static void resolvfile_remove_entries(GList *entries)
61 for (list = entries; list; list = list->next) {
62 struct resolvfile_entry *entry = list->data;
64 resolvfile_list = g_list_remove(resolvfile_list, entry);
66 g_free(entry->server);
67 g_free(entry->domain);
68 g_free(entry->interface);
75 static int resolvfile_export(void)
83 content = g_string_new("# Generated by Connection Manager\n");
86 * Domains and nameservers are added in reverse so that the most
87 * recently appended entry is the primary one. No more than
88 * MAXDNSRCH/MAXNS entries are used.
91 for (count = 0, list = g_list_last(resolvfile_list);
92 list && (count < MAXDNSRCH);
93 list = g_list_previous(list)) {
94 struct resolvfile_entry *entry = list->data;
100 g_string_append_printf(content, "search ");
102 g_string_append_printf(content, "%s ", entry->domain);
107 g_string_append_printf(content, "\n");
109 for (count = 0, list = g_list_last(resolvfile_list);
110 list && (count < MAXNS);
111 list = g_list_previous(list)) {
112 struct resolvfile_entry *entry = list->data;
117 g_string_append_printf(content, "nameserver %s\n",
122 old_umask = umask(022);
124 fd = open("/etc/resolv.conf", O_RDWR | O_CREAT,
125 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
131 if (ftruncate(fd, 0) < 0) {
138 if (write(fd, content->str, content->len) < 0)
145 g_string_free(content, TRUE);
151 int __connman_resolvfile_append(const char *interface, const char *domain,
154 struct resolvfile_entry *entry;
156 DBG("interface %s server %s", interface, server);
158 if (interface == NULL)
161 entry = g_try_new0(struct resolvfile_entry, 1);
165 entry->interface = g_strdup(interface);
166 entry->domain = g_strdup(domain);
167 entry->server = g_strdup(server);
169 resolvfile_list = g_list_append(resolvfile_list, entry);
171 return resolvfile_export();
174 int __connman_resolvfile_remove(const char *interface, const char *domain,
177 GList *list, *matches = NULL;
179 DBG("interface %s server %s", interface, server);
181 for (list = resolvfile_list; list; list = g_list_next(list)) {
182 struct resolvfile_entry *entry = list->data;
184 if (interface != NULL &&
185 g_strcmp0(entry->interface, interface) != 0)
188 if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
191 if (g_strcmp0(entry->server, server) != 0)
194 matches = g_list_append(matches, entry);
197 resolvfile_remove_entries(matches);
199 return resolvfile_export();
202 static void remove_entries(GSList *entries)
206 for (list = entries; list; list = list->next) {
207 struct entry_data *entry = list->data;
209 entry_list = g_slist_remove(entry_list, entry);
211 if (dnsproxy_enabled == TRUE) {
212 __connman_dnsproxy_remove(entry->interface, entry->domain,
215 __connman_resolvfile_remove(entry->interface, entry->domain,
220 g_source_remove(entry->timeout);
221 g_free(entry->server);
222 g_free(entry->domain);
223 g_free(entry->interface);
227 g_slist_free(entries);
230 static gboolean resolver_expire_cb(gpointer user_data)
232 struct entry_data *entry = user_data;
235 DBG("interface %s domain %s server %s",
236 entry->interface, entry->domain, entry->server);
238 list = g_slist_append(NULL, entry);
239 remove_entries(list);
244 static int append_resolver(const char *interface, const char *domain,
245 const char *server, unsigned int lifetime,
248 struct entry_data *entry;
250 DBG("interface %s domain %s server %s lifetime %d flags %d",
251 interface, domain, server, lifetime, flags);
253 if (server == NULL && domain == NULL)
256 entry = g_try_new0(struct entry_data, 1);
260 entry->interface = g_strdup(interface);
261 entry->domain = g_strdup(domain);
262 entry->server = g_strdup(server);
263 entry->flags = flags;
265 entry->timeout = g_timeout_add_seconds(lifetime,
266 resolver_expire_cb, entry);
268 entry_list = g_slist_append(entry_list, entry);
270 if (dnsproxy_enabled == TRUE)
271 __connman_dnsproxy_append(interface, domain, server);
273 __connman_resolvfile_append(interface, domain, server);
279 * connman_resolver_append:
280 * @interface: network interface
281 * @domain: domain limitation
282 * @server: server address
284 * Append resolver server address to current list
286 int connman_resolver_append(const char *interface, const char *domain,
289 DBG("interface %s domain %s server %s", interface, domain, server);
291 return append_resolver(interface, domain, server, 0, 0);
295 * connman_resolver_append_lifetime:
296 * @interface: network interface
297 * @domain: domain limitation
298 * @server: server address
299 * @timeout: server lifetime in seconds
301 * Append resolver server address to current list
303 int connman_resolver_append_lifetime(const char *interface, const char *domain,
304 const char *server, unsigned int lifetime)
308 DBG("interface %s domain %s server %s lifetime %d",
309 interface, domain, server, lifetime);
314 for (list = entry_list; list; list = list->next) {
315 struct entry_data *entry = list->data;
317 if (!entry->timeout ||
318 g_strcmp0(entry->interface, interface) ||
319 g_strcmp0(entry->domain, domain) ||
320 g_strcmp0(entry->server, server))
323 g_source_remove(entry->timeout);
324 entry->timeout = g_timeout_add_seconds(lifetime,
325 resolver_expire_cb, entry);
329 return append_resolver(interface, domain, server, lifetime, 0);
333 * connman_resolver_remove:
334 * @interface: network interface
335 * @domain: domain limitation
336 * @server: server address
338 * Remover resolver server address from current list
340 int connman_resolver_remove(const char *interface, const char *domain,
343 GSList *list, *matches = NULL;
345 DBG("interface %s domain %s server %s", interface, domain, server);
350 for (list = entry_list; list; list = list->next) {
351 struct entry_data *entry = list->data;
353 if (interface != NULL &&
354 g_strcmp0(entry->interface, interface) != 0)
357 if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
360 if (g_strcmp0(entry->server, server) != 0)
363 matches = g_slist_append(matches, entry);
369 remove_entries(matches);
375 * connman_resolver_remove_all:
376 * @interface: network interface
378 * Remove all resolver server address for the specified interface
380 int connman_resolver_remove_all(const char *interface)
382 GSList *list, *matches = NULL;
384 DBG("interface %s", interface);
386 if (interface == NULL)
389 for (list = entry_list; list; list = list->next) {
390 struct entry_data *entry = list->data;
392 if (g_strcmp0(entry->interface, interface) != 0)
395 matches = g_slist_append(matches, entry);
401 remove_entries(matches);
407 * connman_resolver_append_public_server:
408 * @server: server address
410 * Append public resolver server address to current list
412 int connman_resolver_append_public_server(const char *server)
414 DBG("server %s", server);
416 return append_resolver(NULL, NULL, server, 0, RESOLVER_FLAG_PUBLIC);
420 * connman_resolver_remove_public_server:
421 * @server: server address
423 * Remove public resolver server address to current list
425 int connman_resolver_remove_public_server(const char *server)
427 DBG("server %s", server);
429 return connman_resolver_remove(NULL, NULL, server);
433 * connman_resolver_flush:
435 * Flush pending resolver requests
437 void connman_resolver_flush(void)
439 if (dnsproxy_enabled == TRUE)
440 __connman_dnsproxy_flush();
445 int __connman_resolver_init(connman_bool_t dnsproxy)
447 DBG("dnsproxy %d", dnsproxy);
449 if (dnsproxy == FALSE)
452 if (__connman_dnsproxy_init() < 0) {
453 /* Fall back to resolv.conf */
457 dnsproxy_enabled = TRUE;
462 void __connman_resolver_cleanup(void)
466 if (dnsproxy_enabled == TRUE)
467 __connman_dnsproxy_cleanup();