Remove unused "GetVsies" Dbus method.
[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 static const GDBusMethodTable manager_methods[] = {
541         { GDBUS_METHOD("GetProperties",
542                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
543                         get_properties) },
544         { GDBUS_ASYNC_METHOD("SetProperty",
545                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
546                         NULL, set_property) },
547         { GDBUS_METHOD("GetTechnologies",
548                         NULL, GDBUS_ARGS({ "technologies", "a(oa{sv})" }),
549                         get_technologies) },
550         { GDBUS_DEPRECATED_METHOD("RemoveProvider",
551                         GDBUS_ARGS({ "provider", "o" }), NULL,
552                         remove_provider) },
553         { GDBUS_METHOD("GetServices",
554                         NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
555                         get_services) },
556         { GDBUS_METHOD("GetPeers",
557                         NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
558                         get_peers) },
559         { GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider",
560                               GDBUS_ARGS({ "provider", "a{sv}" }),
561                               GDBUS_ARGS({ "path", "o" }),
562                               connect_provider) },
563         { GDBUS_METHOD("RegisterAgent",
564                         GDBUS_ARGS({ "path", "o" }), NULL,
565                         register_agent) },
566         { GDBUS_METHOD("UnregisterAgent",
567                         GDBUS_ARGS({ "path", "o" }), NULL,
568                         unregister_agent) },
569         { GDBUS_METHOD("RegisterCounter",
570                         GDBUS_ARGS({ "path", "o" }, { "accuracy", "u" },
571                                         { "period", "u" }),
572                         NULL, register_counter) },
573         { GDBUS_METHOD("UnregisterCounter",
574                         GDBUS_ARGS({ "path", "o" }), NULL,
575                         unregister_counter) },
576         { GDBUS_ASYNC_METHOD("CreateSession",
577                         GDBUS_ARGS({ "settings", "a{sv}" },
578                                                 { "notifier", "o" }),
579                         GDBUS_ARGS({ "session", "o" }),
580                         create_session) },
581         { GDBUS_METHOD("DestroySession",
582                         GDBUS_ARGS({ "session", "o" }), NULL,
583                         destroy_session) },
584         { GDBUS_ASYNC_METHOD("RequestPrivateNetwork",
585                               NULL, GDBUS_ARGS({ "path", "o" },
586                                                { "settings", "a{sv}" },
587                                                { "socket", "h" }),
588                               request_private_network) },
589         { GDBUS_METHOD("ReleasePrivateNetwork",
590                         GDBUS_ARGS({ "path", "o" }), NULL,
591                         release_private_network) },
592         { GDBUS_ASYNC_METHOD("RegisterPeerService",
593                         GDBUS_ARGS({ "specification", "a{sv}" },
594                                    { "master", "b" }), NULL,
595                         register_peer_service) },
596         { GDBUS_METHOD("UnregisterPeerService",
597                         GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
598                         unregister_peer_service) },
599         { },
600 };
601
602 static const GDBusSignalTable manager_signals[] = {
603         { GDBUS_SIGNAL("PropertyChanged",
604                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
605         { GDBUS_SIGNAL("TechnologyAdded",
606                         GDBUS_ARGS({ "path", "o" },
607                                    { "properties", "a{sv}" })) },
608         { GDBUS_SIGNAL("TechnologyRemoved",
609                         GDBUS_ARGS({ "path", "o" })) },
610         { GDBUS_SIGNAL("ServicesChanged",
611                         GDBUS_ARGS({ "changed", "a(oa{sv})" },
612                                         { "removed", "ao" })) },
613         { GDBUS_SIGNAL("PeersChanged",
614                         GDBUS_ARGS({ "changed", "a(oa{sv})" },
615                                         { "removed", "ao" })) },
616         { },
617 };
618
619 int __connman_manager_init(void)
620 {
621         DBG("");
622
623         connection = connman_dbus_get_connection();
624         if (!connection)
625                 return -1;
626
627         if (connman_notifier_register(&technology_notifier) < 0)
628                 connman_error("Failed to register technology notifier");
629
630         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
631                                         CONNMAN_MANAGER_INTERFACE,
632                                         manager_methods,
633                                         manager_signals, NULL, NULL, NULL);
634
635         connman_state_idle = true;
636
637         return 0;
638 }
639
640 void __connman_manager_cleanup(void)
641 {
642         DBG("");
643
644         if (!connection)
645                 return;
646
647         connman_notifier_unregister(&technology_notifier);
648
649         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
650                                                 CONNMAN_MANAGER_INTERFACE);
651
652         dbus_connection_unref(connection);
653 }