Add support for global offline mode storage
[framework/connectivity/connman.git] / src / manager.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 <gdbus.h>
27
28 #include "connman.h"
29
30 static connman_bool_t global_offlinemode = FALSE;
31
32 connman_bool_t __connman_manager_get_offlinemode(void)
33 {
34         return global_offlinemode;
35 }
36
37 static void append_profiles(DBusMessageIter *dict)
38 {
39         DBusMessageIter entry, value, iter;
40         const char *key = "Profiles";
41
42         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
43                                                                 NULL, &entry);
44
45         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
46
47         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
48                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
49                                                                 &value);
50
51         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
52                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
53         __connman_profile_list(&iter);
54         dbus_message_iter_close_container(&value, &iter);
55
56         dbus_message_iter_close_container(&entry, &value);
57
58         dbus_message_iter_close_container(dict, &entry);
59 }
60
61 static void append_services(DBusMessageIter *dict)
62 {
63         DBusMessageIter entry, value, iter;
64         const char *key = "Services";
65
66         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
67                                                                 NULL, &entry);
68
69         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
70
71         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
72                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
73                                                                 &value);
74
75         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
76                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
77         __connman_service_list(&iter);
78         dbus_message_iter_close_container(&value, &iter);
79
80         dbus_message_iter_close_container(&entry, &value);
81
82         dbus_message_iter_close_container(dict, &entry);
83 }
84
85 static void append_devices(DBusMessageIter *dict)
86 {
87         DBusMessageIter entry, value, iter;
88         const char *key = "Devices";
89
90         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
91                                                                 NULL, &entry);
92
93         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
94
95         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
96                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
97                                                                 &value);
98
99         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
100                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
101         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
102         dbus_message_iter_close_container(&value, &iter);
103
104         dbus_message_iter_close_container(&entry, &value);
105
106         dbus_message_iter_close_container(dict, &entry);
107 }
108
109 static void append_connections(DBusMessageIter *dict)
110 {
111         DBusMessageIter entry, value, iter;
112         const char *key = "Connections";
113
114         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
115                                                                 NULL, &entry);
116
117         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
118
119         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
120                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
121                                                                 &value);
122
123         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
124                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
125         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
126         dbus_message_iter_close_container(&value, &iter);
127
128         dbus_message_iter_close_container(&entry, &value);
129
130         dbus_message_iter_close_container(dict, &entry);
131 }
132
133 static void append_available_technologies(DBusMessageIter *dict)
134 {
135         DBusMessageIter entry, value, iter;
136         const char *key = "AvailableTechnologies";
137
138         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
139                                                                 NULL, &entry);
140
141         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
142
143         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
144                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
145                                                                 &value);
146
147         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
148                                         DBUS_TYPE_STRING_AS_STRING, &iter);
149         __connman_notifier_list_registered(&iter);
150         dbus_message_iter_close_container(&value, &iter);
151
152         dbus_message_iter_close_container(&entry, &value);
153
154         dbus_message_iter_close_container(dict, &entry);
155 }
156
157 static void append_enabled_technologies(DBusMessageIter *dict)
158 {
159         DBusMessageIter entry, value, iter;
160         const char *key = "EnabledTechnologies";
161
162         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
163                                                                 NULL, &entry);
164
165         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
166
167         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
168                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
169                                                                 &value);
170
171         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
172                                         DBUS_TYPE_STRING_AS_STRING, &iter);
173         __connman_notifier_list_enabled(&iter);
174         dbus_message_iter_close_container(&value, &iter);
175
176         dbus_message_iter_close_container(&entry, &value);
177
178         dbus_message_iter_close_container(dict, &entry);
179 }
180
181 static void append_connected_technologies(DBusMessageIter *dict)
182 {
183         DBusMessageIter entry, value, iter;
184         const char *key = "ConnectedTechnologies";
185
186         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
187                                                                 NULL, &entry);
188
189         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
190
191         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
192                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
193                                                                 &value);
194
195         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
196                                         DBUS_TYPE_STRING_AS_STRING, &iter);
197         __connman_notifier_list_connected(&iter);
198         dbus_message_iter_close_container(&value, &iter);
199
200         dbus_message_iter_close_container(&entry, &value);
201
202         dbus_message_iter_close_container(dict, &entry);
203 }
204
205 static DBusMessage *get_properties(DBusConnection *conn,
206                                         DBusMessage *msg, void *data)
207 {
208         DBusMessage *reply;
209         DBusMessageIter array, dict;
210         const char *str;
211
212         DBG("conn %p", conn);
213
214         if (__connman_security_check_privilege(msg,
215                                         CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
216                 return __connman_error_permission_denied(msg);
217
218         reply = dbus_message_new_method_return(msg);
219         if (reply == NULL)
220                 return NULL;
221
222         dbus_message_iter_init_append(reply, &array);
223
224         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
225                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
226                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
227                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
228
229         str = __connman_profile_active_path();
230         if (str != NULL)
231                 connman_dbus_dict_append_variant(&dict, "ActiveProfile",
232                                                 DBUS_TYPE_OBJECT_PATH, &str);
233
234         append_profiles(&dict);
235         append_services(&dict);
236
237         append_devices(&dict);
238         append_connections(&dict);
239
240         if (__connman_element_count(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION) > 0)
241                 str = "online";
242         else
243                 str = "offline";
244
245         connman_dbus_dict_append_variant(&dict, "State",
246                                                 DBUS_TYPE_STRING, &str);
247
248         connman_dbus_dict_append_variant(&dict, "OfflineMode",
249                                 DBUS_TYPE_BOOLEAN, &global_offlinemode);
250
251         append_available_technologies(&dict);
252         append_enabled_technologies(&dict);
253         append_connected_technologies(&dict);
254
255         str = __connman_service_default();
256         if (str != NULL)
257                 connman_dbus_dict_append_variant(&dict, "DefaultTechnology",
258                                                 DBUS_TYPE_STRING, &str);
259
260         dbus_message_iter_close_container(&array, &dict);
261
262         return reply;
263 }
264
265 static DBusMessage *set_property(DBusConnection *conn,
266                                         DBusMessage *msg, void *data)
267 {
268         DBusMessageIter iter, value;
269         const char *name;
270
271         DBG("conn %p", conn);
272
273         if (dbus_message_iter_init(msg, &iter) == FALSE)
274                 return __connman_error_invalid_arguments(msg);
275
276         dbus_message_iter_get_basic(&iter, &name);
277         dbus_message_iter_next(&iter);
278         dbus_message_iter_recurse(&iter, &value);
279
280         if (__connman_security_check_privilege(msg,
281                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
282                 return __connman_error_permission_denied(msg);
283
284         if (g_str_equal(name, "OfflineMode") == TRUE) {
285                 connman_bool_t offlinemode;
286
287                 dbus_message_iter_get_basic(&value, &offlinemode);
288
289                 if (global_offlinemode == offlinemode)
290                         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
291
292                 global_offlinemode = offlinemode;
293
294                 __connman_storage_save_global();
295
296                 __connman_device_set_offlinemode(offlinemode);
297         } else if (g_str_equal(name, "ActiveProfile") == TRUE) {
298                 const char *str;
299
300                 dbus_message_iter_get_basic(&value, &str);
301
302                 return __connman_error_not_supported(msg);
303         } else
304                 return __connman_error_invalid_property(msg);
305
306         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
307 }
308
309 static DBusMessage *get_state(DBusConnection *conn,
310                                         DBusMessage *msg, void *data)
311 {
312         const char *str;
313
314         DBG("conn %p", conn);
315
316         if (__connman_security_check_privilege(msg,
317                                         CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
318                 return __connman_error_permission_denied(msg);
319
320         if (__connman_element_count(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION) > 0)
321                 str = "online";
322         else
323                 str = "offline";
324
325         return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &str,
326                                                 DBUS_TYPE_INVALID);
327 }
328
329 static DBusMessage *add_profile(DBusConnection *conn,
330                                         DBusMessage *msg, void *data)
331 {
332         const char *name;
333
334         DBG("conn %p", conn);
335
336         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
337                                                         DBUS_TYPE_INVALID);
338
339         return __connman_error_not_supported(msg);
340 }
341
342 static DBusMessage *remove_profile(DBusConnection *conn,
343                                         DBusMessage *msg, void *data)
344 {
345         const char *path;
346
347         DBG("conn %p", conn);
348
349         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
350                                                         DBUS_TYPE_INVALID);
351
352         return __connman_error_not_supported(msg);
353 }
354
355 static DBusMessage *request_scan(DBusConnection *conn,
356                                         DBusMessage *msg, void *data)
357 {
358         enum connman_device_type type;
359         const char *str;
360         int err;
361
362         DBG("conn %p", conn);
363
364         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
365                                                         DBUS_TYPE_INVALID);
366
367         if (g_strcmp0(str, "") == 0)
368                 type = CONNMAN_DEVICE_TYPE_UNKNOWN;
369         else if (g_strcmp0(str, "wifi") == 0)
370                 type = CONNMAN_DEVICE_TYPE_WIFI;
371         else if (g_strcmp0(str, "wimax") == 0)
372                 type = CONNMAN_DEVICE_TYPE_WIMAX;
373         else
374                 return __connman_error_invalid_arguments(msg);
375
376         err = __connman_element_request_scan(type);
377         if (err < 0) {
378                 if (err == -EINPROGRESS) {
379                         connman_error("Invalid return code from scan");
380                         err = -EINVAL;
381                 }
382
383                 return __connman_error_failed(msg, -err);
384         }
385
386         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
387 }
388
389 static DBusMessage *enable_technology(DBusConnection *conn,
390                                         DBusMessage *msg, void *data)
391 {
392         enum connman_device_type type;
393         const char *str;
394         int err;
395
396         DBG("conn %p", conn);
397
398         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
399                                                         DBUS_TYPE_INVALID);
400
401         if (g_strcmp0(str, "ethernet") == 0)
402                 type = CONNMAN_DEVICE_TYPE_ETHERNET;
403         else if (g_strcmp0(str, "wifi") == 0)
404                 type = CONNMAN_DEVICE_TYPE_WIFI;
405         else if (g_strcmp0(str, "wimax") == 0)
406                 type = CONNMAN_DEVICE_TYPE_WIMAX;
407         else if (g_strcmp0(str, "bluetooth") == 0)
408                 type = CONNMAN_DEVICE_TYPE_BLUETOOTH;
409         else if (g_strcmp0(str, "gps") == 0)
410                 type = CONNMAN_DEVICE_TYPE_GPS;
411         else
412                 return __connman_error_invalid_arguments(msg);
413
414         err = __connman_element_enable_technology(type);
415         if (err < 0) {
416                 if (err == -EINPROGRESS) {
417                         connman_error("Invalid return code from enable");
418                         err = -EINVAL;
419                 }
420
421                 return __connman_error_failed(msg, -err);
422         }
423
424         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
425 }
426
427 static DBusMessage *disable_technology(DBusConnection *conn,
428                                         DBusMessage *msg, void *data)
429 {
430         enum connman_device_type type;
431         const char *str;
432         int err;
433
434         DBG("conn %p", conn);
435
436         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
437                                                         DBUS_TYPE_INVALID);
438
439         if (g_strcmp0(str, "ethernet") == 0)
440                 type = CONNMAN_DEVICE_TYPE_ETHERNET;
441         else if (g_strcmp0(str, "wifi") == 0)
442                 type = CONNMAN_DEVICE_TYPE_WIFI;
443         else if (g_strcmp0(str, "wimax") == 0)
444                 type = CONNMAN_DEVICE_TYPE_WIMAX;
445         else if (g_strcmp0(str, "bluetooth") == 0)
446                 type = CONNMAN_DEVICE_TYPE_BLUETOOTH;
447         else if (g_strcmp0(str, "gps") == 0)
448                 type = CONNMAN_DEVICE_TYPE_GPS;
449         else
450                 return __connman_error_invalid_arguments(msg);
451
452         err = __connman_element_disable_technology(type);
453         if (err < 0) {
454                 if (err == -EINPROGRESS) {
455                         connman_error("Invalid return code from disable");
456                         err = -EINVAL;
457                 }
458
459                 return __connman_error_failed(msg, -err);
460         }
461
462         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
463 }
464
465 static DBusMessage *connect_service(DBusConnection *conn,
466                                         DBusMessage *msg, void *data)
467 {
468         int err;
469
470         DBG("conn %p", conn);
471
472         if (__connman_security_check_privilege(msg,
473                                         CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
474                 return __connman_error_permission_denied(msg);
475
476         err = __connman_service_create_and_connect(msg);
477         if (err < 0) {
478                 if (err == -EINPROGRESS) {
479                         connman_error("Invalid return code from connect");
480                         err = -EINVAL;
481                 }
482
483                 return __connman_error_failed(msg, -err);
484         }
485
486         return NULL;
487 }
488
489 static DBusMessage *register_agent(DBusConnection *conn,
490                                         DBusMessage *msg, void *data)
491 {
492         DBusMessage *reply;
493         const char *sender, *path;
494
495         DBG("conn %p", conn);
496
497         sender = dbus_message_get_sender(msg);
498
499         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
500                                                         DBUS_TYPE_INVALID);
501
502         reply = dbus_message_new_method_return(msg);
503         if (reply == NULL)
504                 return NULL;
505
506         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
507
508         __connman_agent_register(sender, path);
509
510         return reply;
511 }
512
513 static DBusMessage *unregister_agent(DBusConnection *conn,
514                                         DBusMessage *msg, void *data)
515 {
516         DBusMessage *reply;
517         const char *sender, *path;
518
519         DBG("conn %p", conn);
520
521         sender = dbus_message_get_sender(msg);
522
523         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
524                                                         DBUS_TYPE_INVALID);
525
526         reply = dbus_message_new_method_return(msg);
527         if (reply == NULL)
528                 return NULL;
529
530         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
531
532         __connman_agent_unregister(sender, path);
533
534         return reply;
535 }
536
537 static GDBusMethodTable manager_methods[] = {
538         { "GetProperties",     "",      "a{sv}", get_properties     },
539         { "SetProperty",       "sv",    "",      set_property       },
540         { "GetState",          "",      "s",     get_state          },
541         { "AddProfile",        "s",     "o",     add_profile        },
542         { "RemoveProfile",     "o",     "",      remove_profile     },
543         { "RequestScan",       "s",     "",      request_scan       },
544         { "EnableTechnology",  "s",     "",      enable_technology  },
545         { "DisableTechnology", "s",     "",      disable_technology },
546         { "ConnectService",    "a{sv}", "o",     connect_service,
547                                                 G_DBUS_METHOD_FLAG_ASYNC },
548         { "RegisterAgent",     "o",     "",      register_agent     },
549         { "UnregisterAgent",   "o",     "",      unregister_agent   },
550         { },
551 };
552
553 static GDBusSignalTable manager_signals[] = {
554         { "PropertyChanged", "sv" },
555         { "StateChanged",    "s"  },
556         { },
557 };
558
559 static DBusMessage *nm_sleep(DBusConnection *conn,
560                                         DBusMessage *msg, void *data)
561 {
562         DBusMessage *reply;
563
564         DBG("conn %p", conn);
565
566         reply = dbus_message_new_method_return(msg);
567         if (reply == NULL)
568                 return NULL;
569
570         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
571
572         return reply;
573 }
574
575 static DBusMessage *nm_wake(DBusConnection *conn,
576                                         DBusMessage *msg, void *data)
577 {
578         DBusMessage *reply;
579
580         DBG("conn %p", conn);
581
582         reply = dbus_message_new_method_return(msg);
583         if (reply == NULL)
584                 return NULL;
585
586         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
587
588         return reply;
589 }
590
591 enum {
592         NM_STATE_UNKNOWN = 0,
593         NM_STATE_ASLEEP,
594         NM_STATE_CONNECTING,
595         NM_STATE_CONNECTED,
596         NM_STATE_DISCONNECTED
597 };
598
599 static DBusMessage *nm_state(DBusConnection *conn,
600                                         DBusMessage *msg, void *data)
601 {
602         DBusMessage *reply;
603         dbus_uint32_t state;
604
605         DBG("conn %p", conn);
606
607         reply = dbus_message_new_method_return(msg);
608         if (reply == NULL)
609                 return NULL;
610
611         state = NM_STATE_DISCONNECTED;
612
613         dbus_message_append_args(reply, DBUS_TYPE_UINT32, &state,
614                                                         DBUS_TYPE_INVALID);
615
616         return reply;
617 }
618
619 static GDBusMethodTable nm_methods[] = {
620         { "sleep", "",  "",   nm_sleep        },
621         { "wake",  "",  "",   nm_wake         },
622         { "state", "",  "u",  nm_state        },
623         { },
624 };
625
626 static int manager_load(void)
627 {
628         GKeyFile *keyfile;
629         GError *error = NULL;
630         connman_bool_t offlinemode;
631
632         DBG("");
633
634         keyfile = __connman_storage_open();
635         if (keyfile == NULL)
636                 return -EIO;
637
638         offlinemode = g_key_file_get_boolean(keyfile, "global",
639                                                 "OfflineMode", &error);
640         if (error == NULL) {
641                 global_offlinemode = offlinemode;
642
643                 __connman_device_set_offlinemode(offlinemode);
644         }
645         g_clear_error(&error);
646
647         __connman_storage_close(keyfile, FALSE);
648
649         return 0;
650 }
651
652 static int manager_save(void)
653 {
654         GKeyFile *keyfile;
655
656         DBG("");
657
658         keyfile = __connman_storage_open();
659         if (keyfile == NULL)
660                 return -EIO;
661
662         g_key_file_set_boolean(keyfile, "global",
663                                         "OfflineMode", global_offlinemode);
664
665         __connman_storage_close(keyfile, TRUE);
666
667         return 0;
668 }
669
670 static struct connman_storage manager_storage = {
671         .name           = "manager",
672         .priority       = CONNMAN_STORAGE_PRIORITY_LOW,
673         .global_load    = manager_load,
674         .global_save    = manager_save,
675 };
676
677 static DBusConnection *connection = NULL;
678 static gboolean nm_compat = FALSE;
679
680 int __connman_manager_init(DBusConnection *conn, gboolean compat)
681 {
682         DBG("conn %p", conn);
683
684         connection = dbus_connection_ref(conn);
685         if (connection == NULL)
686                 return -1;
687
688         if (connman_storage_register(&manager_storage) < 0)
689                 connman_error("Failed to register manager storage");
690
691         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
692                                         CONNMAN_MANAGER_INTERFACE,
693                                         manager_methods,
694                                         manager_signals, NULL, NULL, NULL);
695
696         if (compat == TRUE) {
697                 g_dbus_register_interface(connection, NM_PATH, NM_INTERFACE,
698                                         nm_methods, NULL, NULL, NULL, NULL);
699
700                 nm_compat = TRUE;
701         }
702
703         return 0;
704 }
705
706 void __connman_manager_cleanup(void)
707 {
708         DBG("conn %p", connection);
709
710         connman_storage_unregister(&manager_storage);
711
712         if (nm_compat == TRUE) {
713                 g_dbus_unregister_interface(connection, NM_PATH, NM_INTERFACE);
714         }
715
716         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
717                                                 CONNMAN_MANAGER_INTERFACE);
718
719         dbus_connection_unref(connection);
720 }