71439742e81624534b797bea84c46ecc2a9cf1fd
[connman] / src / manager.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gdbus.h>
27
28 #include "connman.h"
29
30 enum connman_policy {
31         CONNMAN_POLICY_UNKNOWN  = 0,
32         CONNMAN_POLICY_SINGLE   = 1,
33         CONNMAN_POLICY_MULTIPLE = 2,
34         CONNMAN_POLICY_ASK      = 3,
35 };
36
37 static enum connman_policy global_policy = CONNMAN_POLICY_SINGLE;
38 static connman_bool_t global_flightmode = FALSE;
39
40 static const char *policy2string(enum connman_policy policy)
41 {
42         switch (policy) {
43         case CONNMAN_POLICY_UNKNOWN:
44                 break;
45         case CONNMAN_POLICY_SINGLE:
46                 return "single";
47         case CONNMAN_POLICY_MULTIPLE:
48                 return "multiple";
49         case CONNMAN_POLICY_ASK:
50                 return "ask";
51         }
52
53         return NULL;
54 }
55
56 static enum connman_policy string2policy(const char *policy)
57 {
58         if (g_str_equal(policy, "single") == TRUE)
59                 return CONNMAN_POLICY_SINGLE;
60         else if (g_str_equal(policy, "multiple") == TRUE)
61                 return CONNMAN_POLICY_MULTIPLE;
62         else if (g_str_equal(policy, "ask") == TRUE)
63                 return CONNMAN_POLICY_ASK;
64         else
65                 return CONNMAN_POLICY_UNKNOWN;
66 }
67
68 static void append_profiles(DBusMessageIter *dict)
69 {
70         DBusMessageIter entry, value, iter;
71         const char *key = "Profiles";
72
73         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
74                                                                 NULL, &entry);
75
76         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
77
78         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
79                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
80                                                                 &value);
81
82         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
83                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
84
85         __connman_profile_list(&iter);
86
87         dbus_message_iter_close_container(&value, &iter);
88
89         dbus_message_iter_close_container(&entry, &value);
90
91         dbus_message_iter_close_container(dict, &entry);
92 }
93
94 static void append_devices(DBusMessageIter *dict)
95 {
96         DBusMessageIter entry, value, iter;
97         const char *key = "Devices";
98
99         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
100                                                                 NULL, &entry);
101
102         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
103
104         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
105                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
106                                                                 &value);
107
108         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
109                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
110
111         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
112
113         dbus_message_iter_close_container(&value, &iter);
114
115         dbus_message_iter_close_container(&entry, &value);
116
117         dbus_message_iter_close_container(dict, &entry);
118 }
119
120 static void append_connections(DBusMessageIter *dict)
121 {
122         DBusMessageIter entry, value, iter;
123         const char *key = "Connections";
124
125         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
126                                                                 NULL, &entry);
127
128         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
129
130         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
131                 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
132                                                                 &value);
133
134         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
135                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
136
137         __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
138
139         dbus_message_iter_close_container(&value, &iter);
140
141         dbus_message_iter_close_container(&entry, &value);
142
143         dbus_message_iter_close_container(dict, &entry);
144 }
145
146 static DBusMessage *get_properties(DBusConnection *conn,
147                                         DBusMessage *msg, void *data)
148 {
149         DBusMessage *reply;
150         DBusMessageIter array, dict;
151         const char *str;
152
153         DBG("conn %p", conn);
154
155         reply = dbus_message_new_method_return(msg);
156         if (reply == NULL)
157                 return NULL;
158
159         dbus_message_iter_init_append(reply, &array);
160
161         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
162                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
163                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
164                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
165
166         append_profiles(&dict);
167
168         append_devices(&dict);
169         append_connections(&dict);
170
171         if (__connman_element_count(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION) > 0)
172                 str = "online";
173         else
174                 str = "offline";
175
176         connman_dbus_dict_append_variant(&dict, "State",
177                                                 DBUS_TYPE_STRING, &str);
178
179         str = policy2string(global_policy);
180         if (str != NULL)
181                 connman_dbus_dict_append_variant(&dict, "Policy",
182                                                 DBUS_TYPE_STRING, &str);
183
184         connman_dbus_dict_append_variant(&dict, "FlightMode",
185                                         DBUS_TYPE_BOOLEAN, &global_flightmode);
186
187         dbus_message_iter_close_container(&array, &dict);
188
189         return reply;
190 }
191
192 static DBusMessage *set_property(DBusConnection *conn,
193                                         DBusMessage *msg, void *data)
194 {
195         DBusMessageIter iter, value;
196         const char *name;
197
198         DBG("conn %p", conn);
199
200         if (dbus_message_iter_init(msg, &iter) == FALSE)
201                 return __connman_error_invalid_arguments(msg);
202
203         dbus_message_iter_get_basic(&iter, &name);
204         dbus_message_iter_next(&iter);
205         dbus_message_iter_recurse(&iter, &value);
206
207         if (__connman_security_check_privileges(msg) < 0)
208                 return __connman_error_permission_denied(msg);
209
210         if (g_str_equal(name, "Policy") == TRUE) {
211                 enum connman_policy policy;
212                 const char *str;
213
214                 dbus_message_iter_get_basic(&value, &str);
215                 policy = string2policy(str);
216                 if (policy == CONNMAN_POLICY_UNKNOWN)
217                         return __connman_error_invalid_arguments(msg);
218
219                 global_policy = policy;
220         } else if (g_str_equal(name, "FlightMode") == TRUE) {
221                 connman_bool_t flightmode;
222
223                 dbus_message_iter_get_basic(&value, &flightmode);
224
225                 if (global_flightmode == flightmode)
226                         return __connman_error_invalid_arguments(msg);
227
228                 global_flightmode = flightmode;
229
230                 __connman_device_set_flightmode(flightmode);
231         }
232
233         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
234 }
235
236 static DBusMessage *register_agent(DBusConnection *conn,
237                                         DBusMessage *msg, void *data)
238 {
239         DBusMessage *reply;
240         const char *sender, *path;
241
242         DBG("conn %p", conn);
243
244         sender = dbus_message_get_sender(msg);
245
246         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
247                                                         DBUS_TYPE_INVALID);
248
249         reply = dbus_message_new_method_return(msg);
250         if (reply == NULL)
251                 return NULL;
252
253         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
254
255         __connman_agent_register(sender, path);
256
257         return reply;
258 }
259
260 static DBusMessage *unregister_agent(DBusConnection *conn,
261                                         DBusMessage *msg, void *data)
262 {
263         DBusMessage *reply;
264         const char *sender, *path;
265
266         DBG("conn %p", conn);
267
268         sender = dbus_message_get_sender(msg);
269
270         dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
271                                                         DBUS_TYPE_INVALID);
272
273         reply = dbus_message_new_method_return(msg);
274         if (reply == NULL)
275                 return NULL;
276
277         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
278
279         __connman_agent_unregister(sender, path);
280
281         return reply;
282 }
283
284 static GDBusMethodTable manager_methods[] = {
285         { "GetProperties",   "",   "a{sv}", get_properties   },
286         { "SetProperty",     "sv", "",      set_property     },
287         { "RegisterAgent",   "o",  "",      register_agent   },
288         { "UnregisterAgent", "o",  "",      unregister_agent },
289         { },
290 };
291
292 static GDBusSignalTable manager_signals[] = {
293         { "PropertyChanged", "sv" },
294         { },
295 };
296
297 static DBusMessage *nm_sleep(DBusConnection *conn,
298                                         DBusMessage *msg, void *data)
299 {
300         DBusMessage *reply;
301
302         DBG("conn %p", conn);
303
304         reply = dbus_message_new_method_return(msg);
305         if (reply == NULL)
306                 return NULL;
307
308         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
309
310         return reply;
311 }
312
313 static DBusMessage *nm_wake(DBusConnection *conn,
314                                         DBusMessage *msg, void *data)
315 {
316         DBusMessage *reply;
317
318         DBG("conn %p", conn);
319
320         reply = dbus_message_new_method_return(msg);
321         if (reply == NULL)
322                 return NULL;
323
324         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
325
326         return reply;
327 }
328
329 enum {
330         NM_STATE_UNKNOWN = 0,
331         NM_STATE_ASLEEP,
332         NM_STATE_CONNECTING,
333         NM_STATE_CONNECTED,
334         NM_STATE_DISCONNECTED
335 };
336
337 static DBusMessage *nm_state(DBusConnection *conn,
338                                         DBusMessage *msg, void *data)
339 {
340         DBusMessage *reply;
341         dbus_uint32_t state;
342
343         DBG("conn %p", conn);
344
345         reply = dbus_message_new_method_return(msg);
346         if (reply == NULL)
347                 return NULL;
348
349         state = NM_STATE_DISCONNECTED;
350
351         dbus_message_append_args(reply, DBUS_TYPE_UINT32, &state,
352                                                         DBUS_TYPE_INVALID);
353
354         return reply;
355 }
356
357 static GDBusMethodTable nm_methods[] = {
358         { "sleep", "",  "",   nm_sleep        },
359         { "wake",  "",  "",   nm_wake         },
360         { "state", "",  "u",  nm_state        },
361         { },
362 };
363
364 static DBusConnection *connection = NULL;
365 static gboolean nm_compat = FALSE;
366
367 int __connman_manager_init(DBusConnection *conn, gboolean compat)
368 {
369         DBG("conn %p", conn);
370
371         connection = dbus_connection_ref(conn);
372         if (connection == NULL)
373                 return -1;
374
375         g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
376                                         CONNMAN_MANAGER_INTERFACE,
377                                         manager_methods,
378                                         manager_signals, NULL, NULL, NULL);
379
380         if (compat == TRUE) {
381                 g_dbus_register_interface(connection, NM_PATH, NM_INTERFACE,
382                                         nm_methods, NULL, NULL, NULL, NULL);
383
384                 nm_compat = TRUE;
385         }
386
387         return 0;
388 }
389
390 void __connman_manager_cleanup(void)
391 {
392         DBG("conn %p", connection);
393
394         if (nm_compat == TRUE) {
395                 g_dbus_unregister_interface(connection, NM_PATH, NM_INTERFACE);
396         }
397
398         g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
399                                                 CONNMAN_MANAGER_INTERFACE);
400
401         dbus_connection_unref(connection);
402 }