[connman] Added Tizen Wi-Fi Mesh
[platform/upstream/connman.git] / src / manager.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 <errno.h>
27
28 #include <gdbus.h>
29
30 #include <connman/agent.h>
31
32 #include "connman.h"
33
34 static bool connman_state_idle;
35 static dbus_bool_t sessionmode;
36
37 static DBusMessage *get_properties(DBusConnection *conn,
38                                         DBusMessage *msg, void *data)
39 {
40         DBusMessage *reply;
41         DBusMessageIter array, dict;
42         dbus_bool_t offlinemode;
43         const char *str;
44 #if defined TIZEN_EXT
45         dbus_bool_t autoconnectmode;
46 #endif
47
48         DBG("conn %p", conn);
49
50         reply = dbus_message_new_method_return(msg);
51         if (!reply)
52                 return NULL;
53
54         dbus_message_iter_init_append(reply, &array);
55
56         connman_dbus_dict_open(&array, &dict);
57
58         str = __connman_notifier_get_state();
59         connman_dbus_dict_append_basic(&dict, "State",
60                                                 DBUS_TYPE_STRING, &str);
61
62         offlinemode = __connman_technology_get_offlinemode();
63         connman_dbus_dict_append_basic(&dict, "OfflineMode",
64                                         DBUS_TYPE_BOOLEAN, &offlinemode);
65
66         connman_dbus_dict_append_basic(&dict, "SessionMode",
67                                         DBUS_TYPE_BOOLEAN,
68                                         &sessionmode);
69 #if defined TIZEN_EXT
70         autoconnectmode = __connman_service_get_auto_connect_mode();
71         connman_dbus_dict_append_basic(&dict, "AutoConnectMode",
72                                         DBUS_TYPE_BOOLEAN,
73                                         &autoconnectmode);
74 #endif
75
76         connman_dbus_dict_close(&array, &dict);
77
78         return reply;
79 }
80
81 static DBusMessage *set_property(DBusConnection *conn,
82                                         DBusMessage *msg, void *data)
83 {
84         DBusMessageIter iter, value;
85         const char *name;
86         int type;
87
88         DBG("conn %p", conn);
89
90         if (!dbus_message_iter_init(msg, &iter))
91                 return __connman_error_invalid_arguments(msg);
92
93         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
94                 return __connman_error_invalid_arguments(msg);
95
96         dbus_message_iter_get_basic(&iter, &name);
97         dbus_message_iter_next(&iter);
98
99         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
100                 return __connman_error_invalid_arguments(msg);
101
102         dbus_message_iter_recurse(&iter, &value);
103
104         type = dbus_message_iter_get_arg_type(&value);
105
106         if (g_str_equal(name, "OfflineMode")) {
107                 dbus_bool_t offlinemode;
108
109                 if (type != DBUS_TYPE_BOOLEAN)
110                         return __connman_error_invalid_arguments(msg);
111
112                 dbus_message_iter_get_basic(&value, &offlinemode);
113
114                 if (offlinemode) {
115                         uid_t uid;
116                         if (connman_dbus_get_connection_unix_user_sync(conn,
117                                                 dbus_message_get_sender(msg),
118                                                 &uid) < 0) {
119                                 DBG("Can not get unix user id!");
120                                 return __connman_error_permission_denied(msg);
121                         }
122
123                         if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
124                                 DBG("Not allow this user to turn on offlinemode now!");
125                                 return __connman_error_permission_denied(msg);
126                         }
127                 }
128                 __connman_technology_set_offlinemode(offlinemode);
129         } else if (g_str_equal(name, "SessionMode")) {
130
131                 if (type != DBUS_TYPE_BOOLEAN)
132                         return __connman_error_invalid_arguments(msg);
133
134                 dbus_message_iter_get_basic(&value, &sessionmode);
135         }
136 #if defined TIZEN_EXT
137         else if (g_str_equal(name, "AutoConnectMode") == TRUE) {
138                 bool automode;
139
140                 if (type != DBUS_TYPE_BOOLEAN)
141                         return __connman_error_invalid_arguments(msg);
142
143                 dbus_message_iter_get_basic(&value, &automode);
144
145                 __connman_service_set_auto_connect_mode(automode);
146         }
147 #endif
148         else
149                 return __connman_error_invalid_property(msg);
150
151         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
152 }
153
154 static void append_technology_structs(DBusMessageIter *iter, void *user_data)
155 {
156         __connman_technology_list_struct(iter);
157 }
158
159 static DBusMessage *get_technologies(DBusConnection *conn,
160                 DBusMessage *msg, void *data)
161 {
162         DBusMessage *reply;
163
164 #if !defined TIZEN_EXT
165         DBG("");
166 #endif
167
168         reply = dbus_message_new_method_return(msg);
169         if (!reply)
170                 return NULL;
171
172         __connman_dbus_append_objpath_dict_array(reply,
173                         append_technology_structs, NULL);
174
175         return reply;
176 }
177
178 static DBusMessage *remove_provider(DBusConnection *conn,
179                                     DBusMessage *msg, void *data)
180 {
181         const char *path;
182         int err;
183
184         DBG("conn %p", conn);
185
186         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
187                                                         DBUS_TYPE_INVALID);
188
189         err = __connman_provider_remove_by_path(path);
190         if (err < 0)
191                 return __connman_error_failed(msg, -err);
192
193         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
194 }
195
196 static DBusConnection *connection = NULL;
197
198 static void idle_state(bool idle)
199 {
200
201         DBG("idle %d", idle);
202
203         connman_state_idle = idle;
204
205         if (!connman_state_idle)
206                 return;
207 }
208
209 static struct connman_notifier technology_notifier = {
210         .name           = "manager",
211         .priority       = CONNMAN_NOTIFIER_PRIORITY_HIGH,
212         .idle_state     = idle_state,
213 };
214
215 static void append_service_structs(DBusMessageIter *iter, void *user_data)
216 {
217         __connman_service_list_struct(iter);
218 }
219
220 static DBusMessage *get_services(DBusConnection *conn,
221                                         DBusMessage *msg, void *data)
222 {
223         DBusMessage *reply;
224
225         reply = dbus_message_new_method_return(msg);
226         if (!reply)
227                 return NULL;
228
229         __connman_dbus_append_objpath_dict_array(reply,
230                         append_service_structs, NULL);
231
232         return reply;
233 }
234
235 static void append_peer_structs(DBusMessageIter *iter, void *user_data)
236 {
237         __connman_peer_list_struct(iter);
238 }
239
240 static DBusMessage *get_peers(DBusConnection *conn,
241                                         DBusMessage *msg, void *data)
242 {
243         DBusMessage *reply;
244
245         reply = dbus_message_new_method_return(msg);
246         if (!reply)
247                 return NULL;
248
249         __connman_dbus_append_objpath_dict_array(reply,
250                                         append_peer_structs, NULL);
251         return reply;
252 }
253
254 static DBusMessage *connect_provider(DBusConnection *conn,
255                                         DBusMessage *msg, void *data)
256 {
257         int err;
258
259         DBG("conn %p", conn);
260
261         err = __connman_provider_create_and_connect(msg);
262         if (err < 0)
263                 return __connman_error_failed(msg, -err);
264
265         return NULL;
266 }
267
268 static DBusMessage *register_agent(DBusConnection *conn,
269                                         DBusMessage *msg, void *data)
270 {
271         const char *sender, *path;
272         int err;
273
274         DBG("conn %p", conn);
275
276         sender = dbus_message_get_sender(msg);
277
278         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
279                                                         DBUS_TYPE_INVALID);
280
281         err = connman_agent_register(sender, path);
282         if (err < 0)
283                 return __connman_error_failed(msg, -err);
284
285         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
286 }
287
288 static DBusMessage *unregister_agent(DBusConnection *conn,
289                                         DBusMessage *msg, void *data)
290 {
291         const char *sender, *path;
292         int err;
293
294         DBG("conn %p", conn);
295
296         sender = dbus_message_get_sender(msg);
297
298         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
299                                                         DBUS_TYPE_INVALID);
300
301         err = connman_agent_unregister(sender, path);
302         if (err < 0)
303                 return __connman_error_failed(msg, -err);
304
305         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
306 }
307
308 static DBusMessage *register_counter(DBusConnection *conn,
309                                         DBusMessage *msg, void *data)
310 {
311         const char *sender, *path;
312         unsigned int accuracy, period;
313         int err;
314
315         DBG("conn %p", conn);
316
317         sender = dbus_message_get_sender(msg);
318
319         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
320                                                 DBUS_TYPE_UINT32, &accuracy,
321                                                 DBUS_TYPE_UINT32, &period,
322                                                         DBUS_TYPE_INVALID);
323
324         /* FIXME: add handling of accuracy parameter */
325
326         err = __connman_counter_register(sender, path, period);
327         if (err < 0)
328                 return __connman_error_failed(msg, -err);
329
330         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
331 }
332
333 static DBusMessage *unregister_counter(DBusConnection *conn,
334                                         DBusMessage *msg, void *data)
335 {
336         const char *sender, *path;
337         int err;
338
339         DBG("conn %p", conn);
340
341         sender = dbus_message_get_sender(msg);
342
343         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
344                                                         DBUS_TYPE_INVALID);
345
346         err = __connman_counter_unregister(sender, path);
347         if (err < 0)
348                 return __connman_error_failed(msg, -err);
349
350         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
351 }
352
353 static DBusMessage *create_session(DBusConnection *conn,
354                                         DBusMessage *msg, void *data)
355 {
356         int err;
357
358         DBG("conn %p", conn);
359
360         err = __connman_session_create(msg);
361         if (err < 0) {
362                 if (err == -EINPROGRESS)
363                         return NULL;
364
365                 return __connman_error_failed(msg, -err);
366         }
367
368         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
369 }
370
371 static DBusMessage *destroy_session(DBusConnection *conn,
372                                         DBusMessage *msg, void *data)
373 {
374         int err;
375
376         DBG("conn %p", conn);
377
378         err = __connman_session_destroy(msg);
379         if (err < 0)
380                 return __connman_error_failed(msg, -err);
381
382         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
383 }
384
385 static DBusMessage *request_private_network(DBusConnection *conn,
386                                         DBusMessage *msg, void *data)
387 {
388         const char *sender;
389         int  err;
390
391         DBG("conn %p", conn);
392
393         sender = dbus_message_get_sender(msg);
394
395         err = __connman_private_network_request(msg, sender);
396         if (err < 0)
397                 return __connman_error_failed(msg, -err);
398
399         return NULL;
400 }
401
402 static DBusMessage *release_private_network(DBusConnection *conn,
403                                         DBusMessage *msg, void *data)
404 {
405         const char *path;
406         int err;
407
408         DBG("conn %p", conn);
409
410         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
411                                                         DBUS_TYPE_INVALID);
412
413         err = __connman_private_network_release(path);
414         if (err < 0)
415                 return __connman_error_failed(msg, -err);
416
417         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
418 }
419
420 static int parse_peers_service_specs(DBusMessageIter *array,
421                         const unsigned char **spec, int *spec_len,
422                         const unsigned char **query, int *query_len,
423                         int *version)
424 {
425         *spec = *query = NULL;
426         *spec_len = *query_len = *version = 0;
427
428         while (dbus_message_iter_get_arg_type(array) ==
429                                                         DBUS_TYPE_DICT_ENTRY) {
430                 DBusMessageIter entry, inter, value;
431                 const char *key;
432
433                 dbus_message_iter_recurse(array, &entry);
434                 dbus_message_iter_get_basic(&entry, &key);
435
436                 dbus_message_iter_next(&entry);
437
438                 dbus_message_iter_recurse(&entry, &inter);
439
440                 if  (!g_strcmp0(key, "BonjourResponse")) {
441                         dbus_message_iter_recurse(&inter, &value);
442                         dbus_message_iter_get_fixed_array(&value,
443                                                         spec, spec_len);
444                 } else if (!g_strcmp0(key, "BonjourQuery")) {
445                         dbus_message_iter_recurse(&inter, &value);
446                         dbus_message_iter_get_fixed_array(&value,
447                                                         query, query_len);
448                 } else if (!g_strcmp0(key, "UpnpService")) {
449                         dbus_message_iter_get_basic(&inter, spec);
450                         *spec_len = strlen((const char *)*spec)+1;
451                 } else if (!g_strcmp0(key, "UpnpVersion")) {
452                         dbus_message_iter_get_basic(&inter, version);
453                 } else if (!g_strcmp0(key, "WiFiDisplayIEs")) {
454                         if (*spec || *query)
455                                 return -EINVAL;
456
457                         dbus_message_iter_recurse(&inter, &value);
458                         dbus_message_iter_get_fixed_array(&value,
459                                                         spec, spec_len);
460                 } else
461                         return -EINVAL;
462
463                 dbus_message_iter_next(array);
464         }
465
466         if ((*query && !*spec && !*version) ||
467                                 (!*spec && !*query) || (!*spec && *version))
468                 return -EINVAL;
469
470         return 0;
471 }
472
473 static DBusMessage *register_peer_service(DBusConnection *conn,
474                                                 DBusMessage *msg, void *data)
475 {
476         const unsigned char *spec, *query;
477         DBusMessageIter iter, array;
478         int spec_len, query_len;
479         dbus_bool_t master;
480         const char *owner;
481         int version;
482         int ret;
483
484         DBG("");
485
486         owner = dbus_message_get_sender(msg);
487
488         dbus_message_iter_init(msg, &iter);
489         dbus_message_iter_recurse(&iter, &array);
490
491         ret = parse_peers_service_specs(&array, &spec, &spec_len,
492                                                 &query, &query_len, &version);
493         if (ret)
494                 goto error;
495
496         dbus_message_iter_next(&iter);
497         dbus_message_iter_get_basic(&iter, &master);
498
499         ret = __connman_peer_service_register(owner, msg, spec, spec_len,
500                                         query, query_len, version,master);
501         if (!ret)
502                 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
503         if (ret == -EINPROGRESS)
504                 return NULL;
505 error:
506         return __connman_error_failed(msg, -ret);
507 }
508
509 static DBusMessage *unregister_peer_service(DBusConnection *conn,
510                                                 DBusMessage *msg, void *data)
511 {
512         const unsigned char *spec, *query;
513         DBusMessageIter iter, array;
514         int spec_len, query_len;
515         const char *owner;
516         int version;
517         int ret;
518
519         DBG("");
520
521         owner = dbus_message_get_sender(msg);
522
523         dbus_message_iter_init(msg, &iter);
524         dbus_message_iter_recurse(&iter, &array);
525
526         ret = parse_peers_service_specs(&array, &spec, &spec_len,
527                                                 &query, &query_len, &version);
528         if (ret)
529                 goto error;
530
531         ret = __connman_peer_service_unregister(owner, spec, spec_len,
532                                                 query, query_len, version);
533         if (!ret)
534                 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
535 error:
536         return __connman_error_failed(msg, -ret);
537
538 }
539
540 #if defined TIZEN_EXT_WIFI_MESH
541 static void append_mesh_peer_structs(DBusMessageIter *iter, void *user_data)
542 {
543         __connman_mesh_peer_list_struct(iter);
544 }
545
546 static DBusMessage *get_mesh_peers(DBusConnection *conn,
547                                         DBusMessage *msg, void *data)
548 {
549         DBusMessage *reply;
550
551         reply = dbus_message_new_method_return(msg);
552         if (!reply)
553                 return NULL;
554
555         __connman_dbus_append_objpath_dict_array(reply,
556                                         append_mesh_peer_structs, NULL);
557         return reply;
558 }
559
560 static DBusMessage *get_connected_mesh_peers(DBusConnection *conn,
561                                         DBusMessage *msg, void *data)
562 {
563         DBusMessage *reply;
564         DBusMessageIter iter, array;
565
566         reply = dbus_message_new_method_return(msg);
567         if (!reply)
568                 return NULL;
569
570         dbus_message_iter_init_append(reply, &iter);
571         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
572                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
573                         DBUS_TYPE_ARRAY_AS_STRING
574                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
575                                         DBUS_TYPE_STRING_AS_STRING
576                                         DBUS_TYPE_VARIANT_AS_STRING
577                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
578                         DBUS_STRUCT_END_CHAR_AS_STRING, &array);
579
580         __connman_mesh_connected_peer_list_struct(&array);
581         dbus_message_iter_close_container(&iter, &array);
582         return reply;
583 }
584
585 static DBusMessage *get_disconnected_mesh_peers(DBusConnection *conn,
586                                         DBusMessage *msg, void *data)
587 {
588         DBusMessage *reply;
589         DBusMessageIter iter, array;
590
591         reply = dbus_message_new_method_return(msg);
592         if (!reply)
593                 return NULL;
594
595         dbus_message_iter_init_append(reply, &iter);
596         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
597                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
598                         DBUS_TYPE_ARRAY_AS_STRING
599                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
600                                         DBUS_TYPE_STRING_AS_STRING
601                                         DBUS_TYPE_VARIANT_AS_STRING
602                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
603                         DBUS_STRUCT_END_CHAR_AS_STRING, &array);
604
605         __connman_mesh_disconnected_peer_list_struct(&array);
606         dbus_message_iter_close_container(&iter, &array);
607         return reply;
608 }
609
610 static DBusMessage *mesh_add_peer(DBusConnection *conn,
611                                         DBusMessage *msg, void *user_data)
612 {
613         const char *addr;
614         int err;
615
616         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
617                                                         DBUS_TYPE_INVALID);
618
619         DBG("Address %s", addr);
620
621         err = __connman_mesh_change_peer_status(msg, addr, CONNMAN_MESH_PEER_ADD);
622         if (err < 0)
623                 return __connman_error_failed(msg, -err);
624
625         return NULL;
626 }
627
628 static DBusMessage *mesh_remove_peer(DBusConnection *conn,
629                                         DBusMessage *msg, void *user_data)
630 {
631         const char *addr;
632         int err;
633
634         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
635                                                         DBUS_TYPE_INVALID);
636
637         DBG("Address %s", addr);
638
639         err = __connman_mesh_change_peer_status(msg, addr,
640                                                                                 CONNMAN_MESH_PEER_REMOVE);
641         if (err < 0)
642                 return __connman_error_failed(msg, -err);
643
644         return NULL;
645 }
646 #endif
647
648 static const GDBusMethodTable manager_methods[] = {
649         { GDBUS_METHOD("GetProperties",
650                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
651                         get_properties) },
652         { GDBUS_ASYNC_METHOD("SetProperty",
653                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
654                         NULL, set_property) },
655         { GDBUS_METHOD("GetTechnologies",
656                         NULL, GDBUS_ARGS({ "technologies", "a(oa{sv})" }),
657                         get_technologies) },
658         { GDBUS_DEPRECATED_METHOD("RemoveProvider",
659                         GDBUS_ARGS({ "provider", "o" }), NULL,
660                         remove_provider) },
661         { GDBUS_METHOD("GetServices",
662                         NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
663                         get_services) },
664         { GDBUS_METHOD("GetPeers",
665                         NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
666                         get_peers) },
667         { GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider",
668                               GDBUS_ARGS({ "provider", "a{sv}" }),
669                               GDBUS_ARGS({ "path", "o" }),
670                               connect_provider) },
671         { GDBUS_METHOD("RegisterAgent",
672                         GDBUS_ARGS({ "path", "o" }), NULL,
673                         register_agent) },
674         { GDBUS_METHOD("UnregisterAgent",
675                         GDBUS_ARGS({ "path", "o" }), NULL,
676                         unregister_agent) },
677         { GDBUS_METHOD("RegisterCounter",
678                         GDBUS_ARGS({ "path", "o" }, { "accuracy", "u" },
679                                         { "period", "u" }),
680                         NULL, register_counter) },
681         { GDBUS_METHOD("UnregisterCounter",
682                         GDBUS_ARGS({ "path", "o" }), NULL,
683                         unregister_counter) },
684         { GDBUS_ASYNC_METHOD("CreateSession",
685                         GDBUS_ARGS({ "settings", "a{sv}" },
686                                                 { "notifier", "o" }),
687                         GDBUS_ARGS({ "session", "o" }),
688                         create_session) },
689         { GDBUS_METHOD("DestroySession",
690                         GDBUS_ARGS({ "session", "o" }), NULL,
691                         destroy_session) },
692         { GDBUS_ASYNC_METHOD("RequestPrivateNetwork",
693                               NULL, GDBUS_ARGS({ "path", "o" },
694                                                { "settings", "a{sv}" },
695                                                { "socket", "h" }),
696                               request_private_network) },
697         { GDBUS_METHOD("ReleasePrivateNetwork",
698                         GDBUS_ARGS({ "path", "o" }), NULL,
699                         release_private_network) },
700         { GDBUS_ASYNC_METHOD("RegisterPeerService",
701                         GDBUS_ARGS({ "specification", "a{sv}" },
702                                    { "master", "b" }), NULL,
703                         register_peer_service) },
704         { GDBUS_METHOD("UnregisterPeerService",
705                         GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
706                         unregister_peer_service) },
707 #if defined TIZEN_EXT_WIFI_MESH
708         { GDBUS_METHOD("GetMeshPeers",
709                         NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
710                         get_mesh_peers) },
711         { GDBUS_METHOD("GetConnectedMeshPeers",
712                         NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
713                         get_connected_mesh_peers) },
714         { GDBUS_METHOD("GetDisconnectedMeshPeers",
715                         NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
716                         get_disconnected_mesh_peers) },
717         { GDBUS_ASYNC_METHOD("MeshAddPeer", GDBUS_ARGS({ "address", "s" }), NULL,
718                                    mesh_add_peer) },
719         { GDBUS_ASYNC_METHOD("MeshRemovePeer", GDBUS_ARGS({ "address", "s" }), NULL,
720                                    mesh_remove_peer) },
721 #endif
722         { },
723 };
724
725 static const GDBusSignalTable manager_signals[] = {
726         { GDBUS_SIGNAL("PropertyChanged",
727                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
728         { GDBUS_SIGNAL("TechnologyAdded",
729                         GDBUS_ARGS({ "path", "o" },
730                                    { "properties", "a{sv}" })) },
731         { GDBUS_SIGNAL("TechnologyRemoved",
732                         GDBUS_ARGS({ "path", "o" })) },
733         { GDBUS_SIGNAL("ServicesChanged",
734                         GDBUS_ARGS({ "changed", "a(oa{sv})" },
735                                         { "removed", "ao" })) },
736         { GDBUS_SIGNAL("PeersChanged",
737                         GDBUS_ARGS({ "changed", "a(oa{sv})" },
738                                         { "removed", "ao" })) },
739         { },
740 };
741
742 int __connman_manager_init(void)
743 {
744         DBG("");
745
746         connection = connman_dbus_get_connection();
747         if (!connection)
748                 return -1;
749
750         if (connman_notifier_register(&technology_notifier) < 0)
751                 connman_error("Failed to register technology notifier");
752
753         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
754                                         CONNMAN_MANAGER_INTERFACE,
755                                         manager_methods,
756                                         manager_signals, NULL, NULL, NULL);
757
758         connman_state_idle = true;
759
760         return 0;
761 }
762
763 void __connman_manager_cleanup(void)
764 {
765         DBG("");
766
767         if (!connection)
768                 return;
769
770         connman_notifier_unregister(&technology_notifier);
771
772         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
773                                                 CONNMAN_MANAGER_INTERFACE);
774
775         dbus_connection_unref(connection);
776 }