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