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
30 #include <gweb/gresolv.h>
34 static GSList *driver_list = NULL;
35 static GHashTable *server_hash = NULL;
37 static char **system_timeservers = NULL;
39 static GResolv *resolv = NULL;
40 static int resolv_id = 0;
41 static volatile int count;
43 static void resolv_debug(const char *str, void *data)
45 connman_info("%s: %s\n", (const char *) data, str);
47 static void save_timeservers(char **servers)
52 keyfile = __connman_storage_load_global();
54 keyfile = g_key_file_new();
56 for (cnt = 0; servers != NULL && servers[cnt] != NULL; cnt++);
58 g_key_file_set_string_list(keyfile, "global", "Timeservers",
59 (const gchar **)servers, cnt);
61 __connman_storage_save_global(keyfile);
63 g_key_file_free(keyfile);
68 static char **load_timeservers()
72 char **servers = NULL;
74 keyfile = __connman_storage_load_global();
78 servers = g_key_file_get_string_list(keyfile, "global",
79 "Timeservers", NULL, &error);
81 DBG("Error loading timeservers: %s", error->message);
85 g_key_file_free(keyfile);
90 static gint compare_priority(gconstpointer a, gconstpointer b)
92 const struct connman_timeserver_driver *driver1 = a;
93 const struct connman_timeserver_driver *driver2 = b;
95 return driver2->priority - driver1->priority;
99 * connman_timeserver_driver_register:
100 * @driver: timeserver driver definition
102 * Register a new timeserver driver
104 * Returns: %0 on success
106 int connman_timeserver_driver_register(struct connman_timeserver_driver *driver)
108 DBG("driver %p name %s", driver, driver->name);
110 driver_list = g_slist_insert_sorted(driver_list, driver,
117 * connman_timeserver_driver_unregister:
118 * @driver: timeserver driver definition
120 * Remove a previously registered timeserver driver
122 void connman_timeserver_driver_unregister(struct connman_timeserver_driver *driver)
124 DBG("driver %p name %s", driver, driver->name);
126 driver_list = g_slist_remove(driver_list, driver);
130 * connman_timeserver_append:
131 * @server: server address
133 * Append time server server address to current list
135 int connman_timeserver_append(const char *server)
139 DBG("server %s", server);
144 /* This server is already handled by a driver */
145 if (g_hash_table_lookup(server_hash, server))
148 for (list = driver_list; list; list = list->next) {
149 struct connman_timeserver_driver *driver = list->data;
152 if (driver->append == NULL)
155 new_server = g_strdup(server);
156 if (new_server == NULL)
159 if (driver->append(server) == 0) {
160 g_hash_table_insert(server_hash, new_server, driver);
171 * connman_timeserver_remove:
172 * @server: server address
174 * Remover time server server address from current list
176 int connman_timeserver_remove(const char *server)
178 struct connman_timeserver_driver *driver;
180 DBG("server %s", server);
185 driver = g_hash_table_lookup(server_hash, server);
189 g_hash_table_remove(server_hash, server);
191 if (driver->remove == NULL)
194 return driver->remove(server);
197 /* Restart NTP procedure */
198 static void connman_timeserver_restart()
200 if (resolv == NULL) {
201 DBG("No online service.");
205 /* Cancel current lookup */
207 g_resolv_cancel_lookup(resolv, resolv_id);
209 /* Reload system timeserver list */
210 if (system_timeservers != NULL) {
211 g_strfreev(system_timeservers);
212 system_timeservers = NULL;
215 system_timeservers = load_timeservers();
217 if (system_timeservers == NULL)
220 __connman_ntp_stop();
224 __connman_timeserver_sync_next();
227 static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data)
231 DBG("status %d", status);
233 __sync_fetch_and_add(&count, 1);
235 if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
236 if (results != NULL) {
237 for (i = 0; results[i]; i++)
238 DBG("result: %s", results[i]);
240 __connman_ntp_start(results[0]);
246 __connman_timeserver_sync_next();
249 void __connman_timeserver_sync_next()
251 if (system_timeservers == NULL ||
252 system_timeservers[count] == NULL)
255 DBG("Trying timeserver %s", system_timeservers[count]);
258 resolv_id = g_resolv_lookup_hostname(resolv,
259 system_timeservers[count], resolv_result,
263 int __connman_timeserver_sync(struct connman_service *service)
265 char **nameservers = NULL;
268 DBG("service %p", service);
270 i = __connman_service_get_index(service);
274 nameservers = connman_service_get_nameservers(service);
275 if (nameservers == NULL)
278 resolv = g_resolv_new(i);
282 if (getenv("CONNMAN_RESOLV_DEBUG"))
283 g_resolv_set_debug(resolv, resolv_debug, "RESOLV");
285 for (i = 0; nameservers[i] != NULL; i++)
286 g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
290 system_timeservers = load_timeservers();
292 if (system_timeservers == NULL || system_timeservers[count] == NULL) {
293 DBG("No timeservers set.");
297 DBG("Trying server %s", system_timeservers[count]);
299 resolv_id = g_resolv_lookup_hostname(resolv, system_timeservers[count],
300 resolv_result, NULL);
304 void __connman_timeserver_stop()
308 if (resolv != NULL) {
309 g_resolv_unref(resolv);
313 if (system_timeservers != NULL) {
314 g_strfreev(system_timeservers);
315 system_timeservers = NULL;
320 __connman_ntp_stop();
323 int __connman_timeserver_system_append(const char *server)
326 char **servers = NULL;
328 if (server == NULL) {
329 save_timeservers(servers);
333 DBG("server %s", server);
335 servers = load_timeservers();
337 if (servers != NULL) {
340 for (i = 0; servers[i] != NULL; i++)
341 if (g_strcmp0(servers[i], server) == 0) {
346 len = g_strv_length(servers);
347 servers = g_try_renew(char *, servers, len + 2);
350 servers = g_try_new0(char *, len + 2);
356 servers[len] = g_strdup(server);
357 servers[len + 1] = NULL;
359 save_timeservers(servers);
363 connman_timeserver_restart();
368 int __connman_timeserver_system_remove(const char *server)
377 DBG("server %s", server);
379 servers = load_timeservers();
384 len = g_strv_length(servers);
386 if (g_strcmp0(servers[0], server) != 0) {
393 save_timeservers(servers);
397 temp = g_try_new0(char *, len - 1);
403 for (i = 0, j = 0; i < len; i++) {
404 if (g_strcmp0(servers[i], server) != 0) {
405 temp[j] = g_strdup(servers[i]);
409 temp[len - 1] = NULL;
412 servers = g_strdupv(temp);
415 save_timeservers(servers);
418 connman_timeserver_restart();
423 char **__connman_timeserver_system_get()
427 servers = load_timeservers();
431 int __connman_timeserver_init(void)
435 server_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
441 void __connman_timeserver_cleanup(void)
445 g_hash_table_destroy(server_hash);