DA: Skip initializing failed_bssids list when eapol failure case
[platform/upstream/connman.git] / src / clock.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <sys/time.h>
27
28 #include <gdbus.h>
29
30 #include "connman.h"
31
32 enum timezone_updates {
33         TIMEZONE_UPDATES_UNKNOWN = 0,
34         TIMEZONE_UPDATES_MANUAL  = 1,
35         TIMEZONE_UPDATES_AUTO    = 2,
36 };
37
38 static enum time_updates time_updates_config = TIME_UPDATES_AUTO;
39 static enum timezone_updates timezone_updates_config = TIMEZONE_UPDATES_AUTO;
40
41 static char *timezone_config = NULL;
42 #if defined TIZEN_EXT
43 static bool time_updated = false;
44 #endif
45
46 static const char *time_updates2string(enum time_updates value)
47 {
48         switch (value) {
49         case TIME_UPDATES_UNKNOWN:
50                 break;
51         case TIME_UPDATES_MANUAL:
52                 return "manual";
53         case TIME_UPDATES_AUTO:
54                 return "auto";
55         }
56
57         return NULL;
58 }
59
60 static enum time_updates string2time_updates(const char *value)
61 {
62         if (g_strcmp0(value, "manual") == 0)
63                 return TIME_UPDATES_MANUAL;
64         else if (g_strcmp0(value, "auto") == 0)
65                 return TIME_UPDATES_AUTO;
66
67         return TIME_UPDATES_UNKNOWN;
68 }
69
70 static const char *timezone_updates2string(enum timezone_updates value)
71 {
72         switch (value) {
73         case TIMEZONE_UPDATES_UNKNOWN:
74                 break;
75         case TIMEZONE_UPDATES_MANUAL:
76                 return "manual";
77         case TIMEZONE_UPDATES_AUTO:
78                 return "auto";
79         }
80
81         return NULL;
82 }
83
84 static enum timezone_updates string2timezone_updates(const char *value)
85 {
86         if (g_strcmp0(value, "manual") == 0)
87                 return TIMEZONE_UPDATES_MANUAL;
88         else if (g_strcmp0(value, "auto") == 0)
89                 return TIMEZONE_UPDATES_AUTO;
90
91         return TIMEZONE_UPDATES_UNKNOWN;
92 }
93
94 static void clock_properties_load(void)
95 {
96         GKeyFile *keyfile;
97         char *str;
98         enum time_updates time_value;
99         enum timezone_updates timezone_value;
100
101         keyfile = __connman_storage_load_global();
102         if (!keyfile)
103                 return;
104
105         str = g_key_file_get_string(keyfile, "global", "TimeUpdates", NULL);
106
107         time_value = string2time_updates(str);
108         if (time_value != TIME_UPDATES_UNKNOWN)
109                 time_updates_config = time_value;
110
111         g_free(str);
112
113         str = g_key_file_get_string(keyfile, "global", "TimezoneUpdates",
114                         NULL);
115
116         timezone_value = string2timezone_updates(str);
117         if (timezone_value != TIMEZONE_UPDATES_UNKNOWN)
118                 timezone_updates_config = timezone_value;
119
120         g_free(str);
121
122 #if defined TIZEN_EXT
123         str = g_key_file_get_string(keyfile, "global", "Timeservers", NULL);
124
125         if (str && str[0] == ';') {
126                 DBG("Set time_updates_config to MANUAL.");
127                 time_updates_config = TIME_UPDATES_MANUAL;
128         }
129
130         g_free(str);
131 #endif
132
133         g_key_file_free(keyfile);
134 }
135
136 static void clock_properties_save(void)
137 {
138         GKeyFile *keyfile;
139         const char *str;
140
141         keyfile = __connman_storage_load_global();
142         if (!keyfile)
143                 keyfile = g_key_file_new();
144
145         str = time_updates2string(time_updates_config);
146         if (str)
147                 g_key_file_set_string(keyfile, "global", "TimeUpdates", str);
148         else
149                 g_key_file_remove_key(keyfile, "global", "TimeUpdates", NULL);
150
151         str = timezone_updates2string(timezone_updates_config);
152         if (str)
153                 g_key_file_set_string(keyfile, "global", "TimezoneUpdates",
154                                 str);
155         else
156                 g_key_file_remove_key(keyfile, "global", "TimezoneUpdates",
157                                 NULL);
158
159         __connman_storage_save_global(keyfile);
160
161         g_key_file_free(keyfile);
162 }
163
164 enum time_updates __connman_clock_timeupdates(void)
165 {
166         return time_updates_config;
167 }
168
169 static void append_timeservers(DBusMessageIter *iter, void *user_data)
170 {
171         int i;
172         char **timeservers = __connman_timeserver_system_get();
173
174         if (!timeservers)
175                 return;
176
177         for (i = 0; timeservers[i]; i++) {
178                 dbus_message_iter_append_basic(iter,
179                                 DBUS_TYPE_STRING, &timeservers[i]);
180         }
181
182         g_strfreev(timeservers);
183 }
184
185 static DBusMessage *get_properties(DBusConnection *conn,
186                                         DBusMessage *msg, void *data)
187 {
188         DBusMessage *reply;
189         DBusMessageIter array, dict;
190         dbus_bool_t is_synced;
191         struct timeval tv;
192         const char *str;
193 #if defined TIZEN_EXT
194         dbus_bool_t val = time_updated;
195 #endif
196
197         DBG("conn %p", conn);
198
199         reply = dbus_message_new_method_return(msg);
200         if (!reply)
201                 return NULL;
202
203         dbus_message_iter_init_append(reply, &array);
204
205         connman_dbus_dict_open(&array, &dict);
206
207 #if defined TIZEN_EXT
208         connman_dbus_dict_append_basic(&dict, "TimeUpdated",
209                                                 DBUS_TYPE_BOOLEAN,
210                                                 &val);
211 #endif
212
213         if (gettimeofday(&tv, NULL) == 0) {
214                 dbus_uint64_t val = tv.tv_sec;
215
216                 connman_dbus_dict_append_basic(&dict, "Time",
217                                                 DBUS_TYPE_UINT64, &val);
218         }
219
220         str = time_updates2string(time_updates_config);
221         if (str)
222                 connman_dbus_dict_append_basic(&dict, "TimeUpdates",
223                                                 DBUS_TYPE_STRING, &str);
224
225         if (timezone_config)
226                 connman_dbus_dict_append_basic(&dict, "Timezone",
227                                         DBUS_TYPE_STRING, &timezone_config);
228
229         str = timezone_updates2string(timezone_updates_config);
230         if (str)
231                 connman_dbus_dict_append_basic(&dict, "TimezoneUpdates",
232                                                 DBUS_TYPE_STRING, &str);
233
234         connman_dbus_dict_append_array(&dict, "Timeservers",
235                                 DBUS_TYPE_STRING, append_timeservers, NULL);
236
237         is_synced = __connman_timeserver_is_synced();
238         connman_dbus_dict_append_basic(&dict, "TimeserverSynced",
239                                         DBUS_TYPE_BOOLEAN, &is_synced);
240
241         connman_dbus_dict_close(&array, &dict);
242
243         return reply;
244 }
245
246 static DBusMessage *set_property(DBusConnection *conn,
247                                         DBusMessage *msg, void *data)
248 {
249         DBusMessageIter iter, value;
250         const char *name;
251         int type;
252
253         DBG("conn %p", conn);
254
255         if (!dbus_message_iter_init(msg, &iter))
256                 return __connman_error_invalid_arguments(msg);
257
258         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
259                 return __connman_error_invalid_arguments(msg);
260
261         dbus_message_iter_get_basic(&iter, &name);
262         dbus_message_iter_next(&iter);
263
264         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
265                 return __connman_error_invalid_arguments(msg);
266
267         dbus_message_iter_recurse(&iter, &value);
268
269         type = dbus_message_iter_get_arg_type(&value);
270
271         if (g_str_equal(name, "Time")) {
272 #if defined TIZEN_EXT
273                 /* Tizen updates time (ntp) by system service */
274
275                 return __connman_error_permission_denied(msg);
276 #else
277                 struct timeval tv;
278                 dbus_uint64_t newval;
279
280                 if (type != DBUS_TYPE_UINT64)
281                         return __connman_error_invalid_arguments(msg);
282
283                 if (time_updates_config != TIME_UPDATES_MANUAL)
284                         return __connman_error_permission_denied(msg);
285
286                 dbus_message_iter_get_basic(&value, &newval);
287
288                 tv.tv_sec = newval;
289                 tv.tv_usec = 0;
290
291                 if (settimeofday(&tv, NULL) < 0)
292                         return __connman_error_invalid_arguments(msg);
293
294                 __connman_timeserver_set_synced(false);
295                 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
296                                 CONNMAN_CLOCK_INTERFACE, "Time",
297                                 DBUS_TYPE_UINT64, &newval);
298 #endif
299         } else if (g_str_equal(name, "TimeUpdates")) {
300                 const char *strval;
301                 enum time_updates newval;
302
303                 if (type != DBUS_TYPE_STRING)
304                         return __connman_error_invalid_arguments(msg);
305
306                 dbus_message_iter_get_basic(&value, &strval);
307                 newval = string2time_updates(strval);
308
309                 if (newval == TIME_UPDATES_UNKNOWN)
310                         return __connman_error_invalid_arguments(msg);
311
312                 if (newval == time_updates_config)
313                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
314
315                 time_updates_config = newval;
316
317                 clock_properties_save();
318                 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
319                                 CONNMAN_CLOCK_INTERFACE, "TimeUpdates",
320                                 DBUS_TYPE_STRING, &strval);
321
322                 if (newval == TIME_UPDATES_AUTO) {
323                         struct connman_service *service;
324
325                         service = connman_service_get_default();
326                         __connman_timeserver_conf_update(service);
327                 }
328         } else if (g_str_equal(name, "Timezone")) {
329                 const char *strval;
330
331                 if (type != DBUS_TYPE_STRING)
332                         return __connman_error_invalid_arguments(msg);
333
334                 if (timezone_updates_config != TIMEZONE_UPDATES_MANUAL)
335                         return __connman_error_permission_denied(msg);
336
337                 dbus_message_iter_get_basic(&value, &strval);
338
339                 if (__connman_timezone_change(strval) < 0)
340                         return __connman_error_invalid_arguments(msg);
341         } else if (g_str_equal(name, "TimezoneUpdates")) {
342                 const char *strval;
343                 enum timezone_updates newval;
344
345                 if (type != DBUS_TYPE_STRING)
346                         return __connman_error_invalid_arguments(msg);
347
348                 dbus_message_iter_get_basic(&value, &strval);
349                 newval = string2timezone_updates(strval);
350
351                 if (newval == TIMEZONE_UPDATES_UNKNOWN)
352                         return __connman_error_invalid_arguments(msg);
353
354                 if (newval == timezone_updates_config)
355                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
356
357                 timezone_updates_config = newval;
358
359                 clock_properties_save();
360                 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
361                                 CONNMAN_CLOCK_INTERFACE, "TimezoneUpdates",
362                                 DBUS_TYPE_STRING, &strval);
363         } else if (g_str_equal(name, "Timeservers")) {
364                 DBusMessageIter entry;
365                 char **str = NULL;
366                 GSList *list = NULL;
367                 int count = 0;
368
369                 if (type != DBUS_TYPE_ARRAY)
370                         return __connman_error_invalid_arguments(msg);
371
372                 dbus_message_iter_recurse(&value, &entry);
373
374                 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
375                         const char *val;
376                         GSList *new_head;
377
378                         dbus_message_iter_get_basic(&entry, &val);
379
380                         new_head = __connman_timeserver_add_list(list, val);
381                         if (list != new_head) {
382                                 count++;
383                                 list = new_head;
384                         }
385
386                         dbus_message_iter_next(&entry);
387                 }
388
389                 if (list) {
390                         str = g_new0(char *, count+1);
391
392                         while (list) {
393                                 count--;
394                                 str[count] = list->data;
395                                 list = g_slist_delete_link(list, list);
396                         };
397                 }
398
399                 __connman_timeserver_system_set(str);
400
401 #if defined TIZEN_EXT
402                 if (str) {
403                         if (str[0][0] == '\0') {
404                                 DBG("Set time_updates_config to MANUAL.");
405                                 time_updates_config = TIMEZONE_UPDATES_MANUAL;
406                         } else {
407                                 DBG("Set time_updates_config to AUTO.");
408                                 time_updates_config = TIMEZONE_UPDATES_AUTO;
409                         }
410                 } else {
411                         DBG("Set time_updates_config to MANUAL.");
412                         time_updates_config = TIMEZONE_UPDATES_MANUAL;
413                 }
414 #endif
415
416                 if (str)
417                         g_strfreev(str);
418
419                 connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
420                                 CONNMAN_CLOCK_INTERFACE, "Timeservers",
421                                 DBUS_TYPE_STRING, append_timeservers, NULL);
422         } else if (g_str_equal(name, "TimeserverSynced")) {
423                 return __connman_error_permission_denied(msg);
424         } else
425                 return __connman_error_invalid_property(msg);
426
427         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
428 }
429
430 static const GDBusMethodTable clock_methods[] = {
431         { GDBUS_METHOD("GetProperties",
432                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
433                         get_properties) },
434         { GDBUS_METHOD("SetProperty",
435                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
436                         set_property)   },
437         { },
438 };
439
440 static const GDBusSignalTable clock_signals[] = {
441         { GDBUS_SIGNAL("PropertyChanged",
442                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
443         { },
444 };
445
446 static DBusConnection *connection = NULL;
447
448 #if defined TIZEN_EXT
449 void __connman_clock_set_time_updated(bool updated)
450 {
451         time_updated = updated;
452 }
453 #endif
454
455 void __connman_clock_update_timezone(void)
456 {
457         DBG("");
458
459         g_free(timezone_config);
460         timezone_config = __connman_timezone_lookup();
461
462         if (!timezone_config)
463                 return;
464
465         connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
466                                 CONNMAN_CLOCK_INTERFACE, "Timezone",
467                                 DBUS_TYPE_STRING, &timezone_config);
468 }
469
470 int __connman_clock_init(void)
471 {
472         DBG("");
473
474         connection = connman_dbus_get_connection();
475         if (!connection)
476                 return -1;
477
478         __connman_timezone_init();
479
480         timezone_config = __connman_timezone_lookup();
481
482         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
483                                                 CONNMAN_CLOCK_INTERFACE,
484                                                 clock_methods, clock_signals,
485                                                 NULL, NULL, NULL);
486
487         clock_properties_load();
488         return 0;
489 }
490
491 void __connman_clock_cleanup(void)
492 {
493         DBG("");
494
495         if (!connection)
496                 return;
497
498         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
499                                                 CONNMAN_CLOCK_INTERFACE);
500
501         dbus_connection_unref(connection);
502
503         __connman_timezone_cleanup();
504
505         g_free(timezone_config);
506 }