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