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;
38 static char **timeservers = NULL;
40 static GResolv *resolv = NULL;
41 static int resolv_id = 0;
42 static volatile int count;
44 static void resolv_debug(const char *str, void *data)
46 connman_info("%s: %s\n", (const char *) data, str);
48 static void save_timeservers(char **servers)
53 keyfile = __connman_storage_load_global();
55 keyfile = g_key_file_new();
57 for (cnt = 0; servers != NULL && servers[cnt] != NULL; cnt++);
59 g_key_file_set_string_list(keyfile, "global", "Timeservers",
60 (const gchar **)servers, cnt);
62 __connman_storage_save_global(keyfile);
64 g_key_file_free(keyfile);
69 static char **load_timeservers()
73 char **servers = NULL;
75 keyfile = __connman_storage_load_global();
79 servers = g_key_file_get_string_list(keyfile, "global",
80 "Timeservers", NULL, &error);
82 DBG("Error loading timeservers: %s", error->message);
86 g_key_file_free(keyfile);
91 static gint compare_priority(gconstpointer a, gconstpointer b)
93 const struct connman_timeserver_driver *driver1 = a;
94 const struct connman_timeserver_driver *driver2 = b;
96 return driver2->priority - driver1->priority;
100 * connman_timeserver_driver_register:
101 * @driver: timeserver driver definition
103 * Register a new timeserver driver
105 * Returns: %0 on success
107 int connman_timeserver_driver_register(struct connman_timeserver_driver *driver)
109 DBG("driver %p name %s", driver, driver->name);
111 driver_list = g_slist_insert_sorted(driver_list, driver,
118 * connman_timeserver_driver_unregister:
119 * @driver: timeserver driver definition
121 * Remove a previously registered timeserver driver
123 void connman_timeserver_driver_unregister(struct connman_timeserver_driver *driver)
125 DBG("driver %p name %s", driver, driver->name);
127 driver_list = g_slist_remove(driver_list, driver);
131 * connman_timeserver_append:
132 * @server: server address
134 * Append time server server address to current list
136 int connman_timeserver_append(const char *server)
140 DBG("server %s", server);
145 /* This server is already handled by a driver */
146 if (g_hash_table_lookup(server_hash, server))
149 for (list = driver_list; list; list = list->next) {
150 struct connman_timeserver_driver *driver = list->data;
153 if (driver->append == NULL)
156 new_server = g_strdup(server);
157 if (new_server == NULL)
160 if (driver->append(server) == 0) {
161 g_hash_table_insert(server_hash, new_server, driver);
172 * connman_timeserver_remove:
173 * @server: server address
175 * Remover time server server address from current list
177 int connman_timeserver_remove(const char *server)
179 struct connman_timeserver_driver *driver;
181 DBG("server %s", server);
186 driver = g_hash_table_lookup(server_hash, server);
190 g_hash_table_remove(server_hash, server);
192 if (driver->remove == NULL)
195 return driver->remove(server);
198 /* Restart NTP procedure */
199 static void connman_timeserver_restart()
201 /* If service timeservers are in use, dont restart ntp */
202 if (timeservers != NULL)
205 if (resolv == NULL) {
206 DBG("No online service.");
210 /* Cancel current lookup */
212 g_resolv_cancel_lookup(resolv, resolv_id);
214 /* Reload system timeserver list */
215 if (system_timeservers != NULL) {
216 g_strfreev(system_timeservers);
217 system_timeservers = NULL;
220 system_timeservers = load_timeservers();
222 if (system_timeservers == NULL)
225 __connman_ntp_stop();
229 __connman_timeserver_sync_next();
232 static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data)
236 DBG("status %d", status);
238 __sync_fetch_and_add(&count, 1);
240 if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
241 if (results != NULL) {
242 for (i = 0; results[i]; i++)
243 DBG("result: %s", results[i]);
245 __connman_ntp_start(results[0]);
251 __connman_timeserver_sync_next();
254 void __connman_timeserver_sync_next()
256 if (system_timeservers == NULL ||
257 system_timeservers[count] == NULL)
260 DBG("Trying timeserver %s", system_timeservers[count]);
263 resolv_id = g_resolv_lookup_hostname(resolv,
264 system_timeservers[count], resolv_result,
268 int __connman_timeserver_sync(struct connman_service *service)
270 char **nameservers = NULL;
273 DBG("service %p", service);
275 i = __connman_service_get_index(service);
279 nameservers = connman_service_get_nameservers(service);
280 if (nameservers == NULL)
283 resolv = g_resolv_new(i);
287 if (getenv("CONNMAN_RESOLV_DEBUG"))
288 g_resolv_set_debug(resolv, resolv_debug, "RESOLV");
290 for (i = 0; nameservers[i] != NULL; i++)
291 g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
295 system_timeservers = load_timeservers();
297 timeservers = connman_service_get_timeservers(service);
299 if (timeservers != NULL && timeservers[0] != NULL) {
300 DBG("Using service tiemservers");
301 __connman_ntp_start(timeservers[0]);
305 if (system_timeservers == NULL || system_timeservers[count] == NULL) {
306 DBG("No timeservers set.");
310 DBG("Trying server %s", system_timeservers[count]);
312 resolv_id = g_resolv_lookup_hostname(resolv, system_timeservers[count],
313 resolv_result, NULL);
317 void __connman_timeserver_stop()
321 if (resolv != NULL) {
322 g_resolv_unref(resolv);
326 if (system_timeservers != NULL) {
327 g_strfreev(system_timeservers);
328 system_timeservers = NULL;
335 __connman_ntp_stop();
338 int __connman_timeserver_system_append(const char *server)
341 char **servers = NULL;
343 if (server == NULL) {
344 save_timeservers(servers);
348 DBG("server %s", server);
350 servers = load_timeservers();
352 if (servers != NULL) {
355 for (i = 0; servers[i] != NULL; i++)
356 if (g_strcmp0(servers[i], server) == 0) {
361 len = g_strv_length(servers);
362 servers = g_try_renew(char *, servers, len + 2);
365 servers = g_try_new0(char *, len + 2);
371 servers[len] = g_strdup(server);
372 servers[len + 1] = NULL;
374 save_timeservers(servers);
378 connman_timeserver_restart();
383 int __connman_timeserver_system_remove(const char *server)
392 DBG("server %s", server);
394 servers = load_timeservers();
399 len = g_strv_length(servers);
401 if (g_strcmp0(servers[0], server) != 0) {
408 save_timeservers(servers);
412 temp = g_try_new0(char *, len - 1);
418 for (i = 0, j = 0; i < len; i++) {
419 if (g_strcmp0(servers[i], server) != 0) {
420 temp[j] = g_strdup(servers[i]);
424 temp[len - 1] = NULL;
427 servers = g_strdupv(temp);
430 save_timeservers(servers);
433 connman_timeserver_restart();
438 char **__connman_timeserver_system_get()
442 servers = load_timeservers();
446 int __connman_timeserver_init(void)
450 server_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
456 void __connman_timeserver_cleanup(void)
460 g_hash_table_destroy(server_hash);