element: Remove element.c
[platform/upstream/connman.git] / src / manager.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  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.h"
31
32 static DBusMessage *get_properties(DBusConnection *conn,
33                                         DBusMessage *msg, void *data)
34 {
35         DBusMessage *reply;
36         DBusMessageIter array, dict;
37         connman_bool_t offlinemode, sessionmode;
38         const char *str;
39
40         DBG("conn %p", conn);
41
42         reply = dbus_message_new_method_return(msg);
43         if (reply == NULL)
44                 return NULL;
45
46         dbus_message_iter_init_append(reply, &array);
47
48         connman_dbus_dict_open(&array, &dict);
49
50         str = __connman_profile_active_path();
51         if (str != NULL)
52                 connman_dbus_dict_append_basic(&dict, "ActiveProfile",
53                                                 DBUS_TYPE_OBJECT_PATH, &str);
54
55         connman_dbus_dict_append_array(&dict, "Services",
56                         DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL);
57         connman_dbus_dict_append_array(&dict, "Technologies",
58                         DBUS_TYPE_OBJECT_PATH, __connman_technology_list, NULL);
59
60         str = __connman_notifier_get_state();
61         connman_dbus_dict_append_basic(&dict, "State",
62                                                 DBUS_TYPE_STRING, &str);
63
64         offlinemode = __connman_profile_get_offlinemode();
65         connman_dbus_dict_append_basic(&dict, "OfflineMode",
66                                         DBUS_TYPE_BOOLEAN, &offlinemode);
67
68         connman_dbus_dict_append_array(&dict, "AvailableTechnologies",
69                 DBUS_TYPE_STRING, __connman_notifier_list_registered, NULL);
70         connman_dbus_dict_append_array(&dict, "EnabledTechnologies",
71                 DBUS_TYPE_STRING, __connman_notifier_list_enabled, NULL);
72         connman_dbus_dict_append_array(&dict, "ConnectedTechnologies",
73                 DBUS_TYPE_STRING, __connman_notifier_list_connected, NULL);
74
75         str = __connman_service_default();
76         if (str != NULL)
77                 connman_dbus_dict_append_basic(&dict, "DefaultTechnology",
78                                                 DBUS_TYPE_STRING, &str);
79
80         connman_dbus_dict_append_array(&dict, "AvailableDebugs",
81                         DBUS_TYPE_STRING, __connman_debug_list_available, NULL);
82         connman_dbus_dict_append_array(&dict, "EnabledDebugs",
83                         DBUS_TYPE_STRING, __connman_debug_list_enabled, NULL);
84
85         sessionmode = __connman_session_mode();
86         connman_dbus_dict_append_basic(&dict, "SessionMode",
87                                         DBUS_TYPE_BOOLEAN,
88                                         &sessionmode);
89
90         connman_dbus_dict_close(&array, &dict);
91
92         return reply;
93 }
94
95 static DBusMessage *set_property(DBusConnection *conn,
96                                         DBusMessage *msg, void *data)
97 {
98         DBusMessageIter iter, value;
99         const char *name;
100         int type;
101
102         DBG("conn %p", conn);
103
104         if (dbus_message_iter_init(msg, &iter) == FALSE)
105                 return __connman_error_invalid_arguments(msg);
106
107         dbus_message_iter_get_basic(&iter, &name);
108         dbus_message_iter_next(&iter);
109         dbus_message_iter_recurse(&iter, &value);
110
111         type = dbus_message_iter_get_arg_type(&value);
112
113         if (g_str_equal(name, "OfflineMode") == TRUE) {
114                 connman_bool_t offlinemode;
115
116                 if (type != DBUS_TYPE_BOOLEAN)
117                         return __connman_error_invalid_arguments(msg);
118
119                 dbus_message_iter_get_basic(&value, &offlinemode);
120
121                 __connman_profile_set_offlinemode(offlinemode, TRUE);
122
123                 __connman_profile_save_default();
124         } else if (g_str_equal(name, "ActiveProfile") == TRUE) {
125                 const char *str;
126
127                 dbus_message_iter_get_basic(&value, &str);
128
129                 return __connman_error_not_supported(msg);
130         } else if (g_str_equal(name, "SessionMode") == TRUE) {
131                 connman_bool_t sessionmode;
132
133                 if (type != DBUS_TYPE_BOOLEAN)
134                         return __connman_error_invalid_arguments(msg);
135
136                 dbus_message_iter_get_basic(&value, &sessionmode);
137
138                 __connman_session_set_mode(sessionmode);
139         } else
140                 return __connman_error_invalid_property(msg);
141
142         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
143 }
144
145 static DBusMessage *get_state(DBusConnection *conn,
146                                         DBusMessage *msg, void *data)
147 {
148         const char *str;
149
150         DBG("conn %p", conn);
151
152         str = __connman_notifier_get_state();
153
154         return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &str,
155                                                 DBUS_TYPE_INVALID);
156 }
157
158 static DBusMessage *remove_provider(DBusConnection *conn,
159                                     DBusMessage *msg, void *data)
160 {
161         const char *path;
162         int err;
163
164         DBG("conn %p", conn);
165
166         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
167                                                         DBUS_TYPE_INVALID);
168
169         err = __connman_provider_remove(path);
170         if (err < 0)
171                 return __connman_error_failed(msg, -err);
172
173         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
174 }
175
176 static DBusMessage *request_scan(DBusConnection *conn,
177                                         DBusMessage *msg, void *data)
178 {
179         enum connman_service_type type;
180         const char *str;
181         int err;
182
183         DBG("conn %p", conn);
184
185         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
186                                                         DBUS_TYPE_INVALID);
187
188         if (g_strcmp0(str, "") == 0)
189                 type = CONNMAN_SERVICE_TYPE_UNKNOWN;
190         else if (g_strcmp0(str, "wifi") == 0)
191                 type = CONNMAN_SERVICE_TYPE_WIFI;
192         else if (g_strcmp0(str, "wimax") == 0)
193                 type = CONNMAN_SERVICE_TYPE_WIMAX;
194         else
195                 return __connman_error_invalid_arguments(msg);
196
197         err = __connman_device_request_scan(type);
198         if (err < 0) {
199                 if (err == -EINPROGRESS) {
200                         connman_error("Invalid return code from scan");
201                         err = -EINVAL;
202                 }
203
204                 return __connman_error_failed(msg, -err);
205         }
206
207         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
208 }
209
210 static DBusConnection *connection = NULL;
211
212 static enum connman_service_type technology_type;
213 static connman_bool_t technology_enabled;
214 static DBusMessage *technology_pending = NULL;
215 static guint technology_timeout = 0;
216
217 static void technology_reply(int error)
218 {
219         DBG("");
220
221         if (technology_timeout > 0) {
222                 g_source_remove(technology_timeout);
223                 technology_timeout = 0;
224         }
225
226         if (technology_pending != NULL) {
227                 if (error > 0) {
228                         DBusMessage *reply;
229
230                         reply = __connman_error_failed(technology_pending,
231                                                                 error);
232                         if (reply != NULL)
233                                 g_dbus_send_message(connection, reply);
234                 } else
235                         g_dbus_send_reply(connection, technology_pending,
236                                                         DBUS_TYPE_INVALID);
237
238                 dbus_message_unref(technology_pending);
239                 technology_pending = NULL;
240         }
241
242         technology_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
243 }
244
245 static gboolean technology_abort(gpointer user_data)
246 {
247         DBG("");
248
249         technology_timeout = 0;
250
251         technology_reply(ETIMEDOUT);
252
253         return FALSE;
254 }
255
256 static void technology_notify(enum connman_service_type type,
257                                                 connman_bool_t enabled)
258 {
259         DBG("type %d enabled %d", type, enabled);
260
261         if (type == technology_type && enabled == technology_enabled)
262                 technology_reply(0);
263 }
264
265 static struct connman_notifier technology_notifier = {
266         .name           = "manager",
267         .priority       = CONNMAN_NOTIFIER_PRIORITY_HIGH,
268         .service_enabled= technology_notify,
269 };
270
271 static DBusMessage *enable_technology(DBusConnection *conn,
272                                         DBusMessage *msg, void *data)
273 {
274         enum connman_service_type type;
275         const char *str;
276         int err;
277
278         DBG("conn %p", conn);
279
280         if (technology_pending != NULL)
281                 return __connman_error_in_progress(msg);
282
283         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
284                                                         DBUS_TYPE_INVALID);
285
286         if (g_strcmp0(str, "ethernet") == 0)
287                 type = CONNMAN_SERVICE_TYPE_ETHERNET;
288         else if (g_strcmp0(str, "wifi") == 0)
289                 type = CONNMAN_SERVICE_TYPE_WIFI;
290         else if (g_strcmp0(str, "wimax") == 0)
291                 type = CONNMAN_SERVICE_TYPE_WIMAX;
292         else if (g_strcmp0(str, "bluetooth") == 0)
293                 type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
294         else if (g_strcmp0(str, "cellular") == 0)
295                 type = CONNMAN_SERVICE_TYPE_CELLULAR;
296         else
297                 return __connman_error_invalid_arguments(msg);
298
299         if (__connman_notifier_is_registered(type) == FALSE)
300                 return __connman_error_not_registered(msg);
301
302         if (__connman_notifier_is_enabled(type) == TRUE)
303                 return __connman_error_already_enabled(msg);
304
305         technology_type = type;
306         technology_enabled = TRUE;
307         technology_pending = dbus_message_ref(msg);
308
309         err = __connman_device_enable_technology(type);
310         if (err < 0 && err != -EINPROGRESS)
311                 technology_reply(-err);
312         else
313                 technology_timeout = g_timeout_add_seconds(15,
314                                                 technology_abort, NULL);
315
316         return NULL;
317 }
318
319 static DBusMessage *disable_technology(DBusConnection *conn,
320                                         DBusMessage *msg, void *data)
321 {
322         enum connman_service_type type;
323         const char *str;
324         int err;
325
326         DBG("conn %p", conn);
327
328         if (technology_pending != NULL)
329                 return __connman_error_in_progress(msg);
330
331         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
332                                                         DBUS_TYPE_INVALID);
333
334         if (g_strcmp0(str, "ethernet") == 0)
335                 type = CONNMAN_SERVICE_TYPE_ETHERNET;
336         else if (g_strcmp0(str, "wifi") == 0)
337                 type = CONNMAN_SERVICE_TYPE_WIFI;
338         else if (g_strcmp0(str, "wimax") == 0)
339                 type = CONNMAN_SERVICE_TYPE_WIMAX;
340         else if (g_strcmp0(str, "bluetooth") == 0)
341                 type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
342         else if (g_strcmp0(str, "cellular") == 0)
343                 type = CONNMAN_SERVICE_TYPE_CELLULAR;
344         else
345                 return __connman_error_invalid_arguments(msg);
346
347         if (__connman_notifier_is_registered(type) == FALSE)
348                 return __connman_error_not_registered(msg);
349
350         if (__connman_notifier_is_enabled(type) == FALSE)
351                 return __connman_error_already_disabled(msg);
352
353         technology_type = type;
354         technology_enabled = FALSE;
355         technology_pending = dbus_message_ref(msg);
356
357         err = __connman_device_disable_technology(type);
358         if (err < 0 && err != -EINPROGRESS)
359                 technology_reply(-err);
360         else
361                 technology_timeout = g_timeout_add_seconds(10,
362                                                 technology_abort, NULL);
363
364         return NULL;
365 }
366
367 static DBusMessage *get_services(DBusConnection *conn,
368                                         DBusMessage *msg, void *data)
369 {
370         DBusMessage *reply;
371         DBusMessageIter iter, array;
372
373         reply = dbus_message_new_method_return(msg);
374         if (reply == NULL)
375                 return NULL;
376
377         dbus_message_iter_init_append(reply, &iter);
378
379         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
380                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
381                         DBUS_TYPE_OBJECT_PATH_AS_STRING
382                         DBUS_TYPE_ARRAY_AS_STRING
383                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
384                                         DBUS_TYPE_STRING_AS_STRING
385                                         DBUS_TYPE_VARIANT_AS_STRING
386                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
387                         DBUS_STRUCT_END_CHAR_AS_STRING, &array);
388
389         __connman_service_list_struct(&array);
390
391         dbus_message_iter_close_container(&iter, &array);
392
393         return reply;
394 }
395
396 static DBusMessage *lookup_service(DBusConnection *conn,
397                                         DBusMessage *msg, void *data)
398 {
399         const char *pattern, *path;
400         int err;
401
402         DBG("conn %p", conn);
403
404         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
405                                                         DBUS_TYPE_INVALID);
406
407         err = __connman_service_lookup(pattern, &path);
408         if (err < 0)
409                 return __connman_error_failed(msg, -err);
410
411         return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &path,
412                                                         DBUS_TYPE_INVALID);
413 }
414
415 static DBusMessage *connect_service(DBusConnection *conn,
416                                         DBusMessage *msg, void *data)
417 {
418         int err;
419
420         DBG("conn %p", conn);
421
422         if (__connman_session_mode() == TRUE) {
423                 connman_info("Session mode enabled: "
424                                 "direct service connect disabled");
425
426                 return __connman_error_failed(msg, -EINVAL);
427         }
428
429         err = __connman_service_create_and_connect(msg);
430         if (err < 0) {
431                 if (err == -EINPROGRESS) {
432                         connman_error("Invalid return code from connect");
433                         err = -EINVAL;
434                 }
435
436                 return __connman_error_failed(msg, -err);
437         }
438
439         return NULL;
440 }
441
442 static DBusMessage *provision_service(DBusConnection *conn, DBusMessage *msg,
443                                         void *data)
444 {
445         int err;
446
447         DBG("conn %p", conn);
448
449         err = __connman_service_provision(msg);
450         if (err < 0)
451                 return __connman_error_failed(msg, -err);
452
453         return NULL;
454 }
455
456 static DBusMessage *connect_provider(DBusConnection *conn,
457                                         DBusMessage *msg, void *data)
458 {
459         int err;
460
461         DBG("conn %p", conn);
462
463         if (__connman_session_mode() == TRUE) {
464                 connman_info("Session mode enabled: "
465                                 "direct provider connect disabled");
466
467                 return __connman_error_failed(msg, -EINVAL);
468         }
469
470         err = __connman_provider_create_and_connect(msg);
471         if (err < 0) {
472                 if (err == -EINPROGRESS) {
473                         connman_error("Invalid return code from connect");
474                         err = -EINVAL;
475                 }
476
477                 return __connman_error_failed(msg, -err);
478         }
479
480         return NULL;
481 }
482
483 static DBusMessage *register_agent(DBusConnection *conn,
484                                         DBusMessage *msg, void *data)
485 {
486         const char *sender, *path;
487         int err;
488
489         DBG("conn %p", conn);
490
491         sender = dbus_message_get_sender(msg);
492
493         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
494                                                         DBUS_TYPE_INVALID);
495
496         err = __connman_agent_register(sender, path);
497         if (err < 0)
498                 return __connman_error_failed(msg, -err);
499
500         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
501 }
502
503 static DBusMessage *unregister_agent(DBusConnection *conn,
504                                         DBusMessage *msg, void *data)
505 {
506         const char *sender, *path;
507         int err;
508
509         DBG("conn %p", conn);
510
511         sender = dbus_message_get_sender(msg);
512
513         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
514                                                         DBUS_TYPE_INVALID);
515
516         err = __connman_agent_unregister(sender, path);
517         if (err < 0)
518                 return __connman_error_failed(msg, -err);
519
520         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
521 }
522
523 static DBusMessage *register_counter(DBusConnection *conn,
524                                         DBusMessage *msg, void *data)
525 {
526         const char *sender, *path;
527         unsigned int accuracy, period;
528         int err;
529
530         DBG("conn %p", conn);
531
532         sender = dbus_message_get_sender(msg);
533
534         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
535                                                 DBUS_TYPE_UINT32, &accuracy,
536                                                 DBUS_TYPE_UINT32, &period,
537                                                         DBUS_TYPE_INVALID);
538
539         /* FIXME: add handling of accuracy parameter */
540
541         err = __connman_counter_register(sender, path, period);
542         if (err < 0)
543                 return __connman_error_failed(msg, -err);
544
545         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
546 }
547
548 static DBusMessage *unregister_counter(DBusConnection *conn,
549                                         DBusMessage *msg, void *data)
550 {
551         const char *sender, *path;
552         int err;
553
554         DBG("conn %p", conn);
555
556         sender = dbus_message_get_sender(msg);
557
558         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
559                                                         DBUS_TYPE_INVALID);
560
561         err = __connman_counter_unregister(sender, path);
562         if (err < 0)
563                 return __connman_error_failed(msg, -err);
564
565         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
566 }
567
568 static DBusMessage *create_session(DBusConnection *conn,
569                                         DBusMessage *msg, void *data)
570 {
571         int err;
572
573         DBG("conn %p", conn);
574
575         err = __connman_session_create(msg);
576         if (err < 0)
577                 return __connman_error_failed(msg, -err);
578
579         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
580 }
581
582 static DBusMessage *destroy_session(DBusConnection *conn,
583                                         DBusMessage *msg, void *data)
584 {
585         int err;
586
587         DBG("conn %p", conn);
588
589         err = __connman_session_destroy(msg);
590         if (err < 0)
591                 return __connman_error_failed(msg, -err);
592
593         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
594 }
595
596 static DBusMessage *request_private_network(DBusConnection *conn,
597                                         DBusMessage *msg, void *data)
598 {
599         const char *sender;
600         int  err;
601
602         DBG("conn %p", conn);
603
604         sender = dbus_message_get_sender(msg);
605
606         err = __connman_private_network_request(msg, sender);
607         if (err < 0)
608                 return __connman_error_failed(msg, -err);
609
610         return NULL;
611 }
612
613 static DBusMessage *release_private_network(DBusConnection *conn,
614                                         DBusMessage *msg, void *data)
615 {
616         const char *sender;
617         int err;
618
619         DBG("conn %p", conn);
620
621         sender = dbus_message_get_sender(msg);
622
623         err = __connman_private_network_release(sender);
624         if (err < 0)
625                 return __connman_error_failed(msg, -err);
626
627         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
628 }
629
630 static GDBusMethodTable manager_methods[] = {
631         { "GetProperties",     "",      "a{sv}", get_properties     },
632         { "SetProperty",       "sv",    "",      set_property       },
633         { "GetState",          "",      "s",     get_state          },
634         { "RemoveProvider",    "o",     "",      remove_provider    },
635         { "RequestScan",       "s",     "",      request_scan       },
636         { "EnableTechnology",  "s",     "",      enable_technology,
637                                                 G_DBUS_METHOD_FLAG_ASYNC },
638         { "DisableTechnology", "s",     "",      disable_technology,
639                                                 G_DBUS_METHOD_FLAG_ASYNC },
640         { "GetServices",       "",      "a(oa{sv})", get_services   },
641         { "LookupService",     "s",     "o",     lookup_service,    },
642         { "ConnectService",    "a{sv}", "o",     connect_service,
643                                                 G_DBUS_METHOD_FLAG_ASYNC },
644         { "ProvisionService",  "s",     "",      provision_service,
645                                                 G_DBUS_METHOD_FLAG_ASYNC },
646         { "ConnectProvider",   "a{sv}", "o",     connect_provider,
647                                                 G_DBUS_METHOD_FLAG_ASYNC },
648         { "RegisterAgent",     "o",     "",      register_agent     },
649         { "UnregisterAgent",   "o",     "",      unregister_agent   },
650         { "RegisterCounter",   "ouu",   "",      register_counter   },
651         { "UnregisterCounter", "o",     "",      unregister_counter },
652         { "CreateSession",     "a{sv}o", "o",    create_session     },
653         { "DestroySession",    "o",     "",      destroy_session    },
654         { "RequestPrivateNetwork",    "",     "ha{sv}",
655                                                 request_private_network,
656                                                 G_DBUS_METHOD_FLAG_ASYNC },
657         { "ReleasePrivateNetwork",    "",     "",
658                                                 release_private_network },
659         { },
660 };
661
662 static GDBusSignalTable manager_signals[] = {
663         { "PropertyChanged", "sv" },
664         { "StateChanged",    "s"  },
665         { },
666 };
667
668 int __connman_manager_init(void)
669 {
670         DBG("");
671
672         connection = connman_dbus_get_connection();
673         if (connection == NULL)
674                 return -1;
675
676         if (connman_notifier_register(&technology_notifier) < 0)
677                 connman_error("Failed to register technology notifier");
678
679         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
680                                         CONNMAN_MANAGER_INTERFACE,
681                                         manager_methods,
682                                         manager_signals, NULL, NULL, NULL);
683
684         return 0;
685 }
686
687 void __connman_manager_cleanup(void)
688 {
689         DBG("");
690
691         connman_notifier_unregister(&technology_notifier);
692
693         if (connection == NULL)
694                 return;
695
696         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
697                                                 CONNMAN_MANAGER_INTERFACE);
698
699         dbus_connection_unref(connection);
700 }