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