Fix documentation spelling mistakes
[connman] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  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 struct connman_network {
31         struct connman_element element;
32         enum connman_network_type type;
33         gboolean connected;
34         char *identifier;
35         char *path;
36
37         struct connman_network_driver *driver;
38         void *driver_data;
39
40         struct connman_device *device;
41 };
42
43 static DBusMessage *get_properties(DBusConnection *conn,
44                                         DBusMessage *msg, void *data)
45 {
46         struct connman_network *network = data;
47         DBusMessage *reply;
48         DBusMessageIter array, dict;
49
50         DBG("conn %p", conn);
51
52         reply = dbus_message_new_method_return(msg);
53         if (reply == NULL)
54                 return NULL;
55
56         dbus_message_iter_init_append(reply, &array);
57
58         dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
59                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
60                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
61                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
62
63         if (network->identifier != NULL)
64                 connman_dbus_dict_append_variant(&dict, "Name",
65                                 DBUS_TYPE_STRING, &network->identifier);
66
67         connman_dbus_dict_append_variant(&dict, "Connected",
68                                 DBUS_TYPE_BOOLEAN, &network->connected);
69
70         dbus_message_iter_close_container(&array, &dict);
71
72         return reply;
73 }
74
75 static DBusMessage *set_property(DBusConnection *conn,
76                                         DBusMessage *msg, void *data)
77 {
78         DBusMessageIter iter, value;
79         const char *name;
80
81         DBG("conn %p", conn);
82
83         if (dbus_message_iter_init(msg, &iter) == FALSE)
84                 return __connman_error_invalid_arguments(msg);
85
86         dbus_message_iter_get_basic(&iter, &name);
87         dbus_message_iter_next(&iter);
88         dbus_message_iter_recurse(&iter, &value);
89
90         if (__connman_security_check_privileges(msg) < 0)
91                 return __connman_error_permission_denied(msg);
92
93         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
94 }
95
96 static DBusMessage *do_connect(DBusConnection *conn,
97                                         DBusMessage *msg, void *data)
98 {
99         struct connman_network *network = data;
100         int err;
101
102         DBG("conn %p", conn);
103
104         if (network->driver && network->driver->connect) {
105                 err = network->driver->connect(network);
106                 if (err < 0 && err != -EINPROGRESS)
107                         return __connman_error_failed(msg);
108         }
109
110         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
111 }
112
113 static DBusMessage *do_disconnect(DBusConnection *conn,
114                                         DBusMessage *msg, void *data)
115 {
116         struct connman_network *network = data;
117         int err;
118
119         DBG("conn %p", conn);
120
121         if (network->driver && network->driver->disconnect) {
122                 err = network->driver->disconnect(network);
123                 if (err < 0 && err != -EINPROGRESS)
124                         return __connman_error_failed(msg);
125         }
126
127         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
128 }
129
130 static GDBusMethodTable network_methods[] = {
131         { "GetProperties", "",   "a{sv}", get_properties },
132         { "SetProperty",   "sv", "",      set_property   },
133         { "Connect",       "",   "",      do_connect     },
134         { "Disconnect",    "",   "",      do_disconnect  },
135         { },
136 };
137
138 static GDBusSignalTable network_signals[] = {
139         { "PropertyChanged", "sv" },
140         { },
141 };
142
143 static DBusConnection *connection;
144
145 static void emit_networks_signal(void)
146 {
147 }
148
149 static int register_interface(struct connman_element *element)
150 {
151         struct connman_network *network = element->network;
152
153         DBG("element %p name %s", element, element->name);
154
155         g_dbus_unregister_interface(connection, element->path,
156                                                 CONNMAN_NETWORK_INTERFACE);
157
158         if (g_dbus_register_interface(connection, element->path,
159                                         CONNMAN_NETWORK_INTERFACE,
160                                         network_methods, network_signals,
161                                         NULL, network, NULL) == FALSE) {
162                 connman_error("Failed to register %s network", element->path);
163                 return -EIO;
164         }
165
166         emit_networks_signal();
167
168         return 0;
169 }
170
171 static void unregister_interface(struct connman_element *element)
172 {
173         DBG("element %p name %s", element, element->name);
174
175         emit_networks_signal();
176
177         g_dbus_unregister_interface(connection, element->path,
178                                                 CONNMAN_NETWORK_INTERFACE);
179 }
180
181 static GSList *driver_list = NULL;
182
183 static gint compare_priority(gconstpointer a, gconstpointer b)
184 {
185         const struct connman_network_driver *driver1 = a;
186         const struct connman_network_driver *driver2 = b;
187
188         return driver2->priority - driver1->priority;
189 }
190
191 /**
192  * connman_network_driver_register:
193  * @driver: network driver definition
194  *
195  * Register a new network driver
196  *
197  * Returns: %0 on success
198  */
199 int connman_network_driver_register(struct connman_network_driver *driver)
200 {
201         DBG("driver %p name %s", driver, driver->name);
202
203         driver_list = g_slist_insert_sorted(driver_list, driver,
204                                                         compare_priority);
205
206         return 0;
207 }
208
209 /**
210  * connman_network_driver_unregister:
211  * @driver: network driver definition
212  *
213  * Remove a previously registered network driver
214  */
215 void connman_network_driver_unregister(struct connman_network_driver *driver)
216 {
217         DBG("driver %p name %s", driver, driver->name);
218
219         driver_list = g_slist_remove(driver_list, driver);
220 }
221
222 static void network_destruct(struct connman_element *element)
223 {
224         struct connman_network *network = element->network;
225
226         DBG("element %p name %s", element, element->name);
227
228         g_free(network->path);
229         g_free(network->identifier);
230 }
231
232 /**
233  * connman_network_create:
234  * @identifier: network identifier (for example an unqiue name)
235  *
236  * Allocate a new network and assign the #identifier to it.
237  *
238  * Returns: a newly-allocated #connman_network structure
239  */
240 struct connman_network *connman_network_create(const char *identifier,
241                                                 enum connman_network_type type)
242 {
243         struct connman_network *network;
244
245         DBG("identifier %s type %d", identifier, type);
246
247         network = g_try_new0(struct connman_network, 1);
248         if (network == NULL)
249                 return NULL;
250
251         DBG("network %p", network);
252
253         network->element.refcount = 1;
254
255         network->element.name = g_strdup(identifier);
256         network->element.type = CONNMAN_ELEMENT_TYPE_NETWORK;
257         network->element.index = -1;
258
259         switch (type) {
260         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
261         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
262                 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH;
263                 break;
264         case CONNMAN_NETWORK_TYPE_HSO:
265                 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_CELLULAR;
266                 break;
267         default:
268                 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
269                 break;
270         }
271
272         network->element.network = network;
273         network->element.destruct = network_destruct;
274
275         network->type = type;
276         network->identifier = g_strdup(identifier);
277
278         return network;
279 }
280
281 /**
282  * connman_network_ref:
283  * @network: network structure
284  *
285  * Increase reference counter of  network
286  */
287 struct connman_network *connman_network_ref(struct connman_network *network)
288 {
289         if (connman_element_ref(&network->element) == NULL)
290                 return NULL;
291
292         return network;
293 }
294
295 /**
296  * connman_network_unref:
297  * @network: network structure
298  *
299  * Decrease reference counter of network
300  */
301 void connman_network_unref(struct connman_network *network)
302 {
303         connman_element_unref(&network->element);
304 }
305
306 /**
307  * connman_network_get_identifier:
308  * @network: network structure
309  *
310  * Get identifier of network
311  */
312 const char *connman_network_get_identifier(struct connman_network *network)
313 {
314         return network->identifier;
315 }
316
317 /**
318  * connman_network_set_path:
319  * @network: network structure
320  * @path: path name
321  *
322  * Set path name of network
323  */
324 void connman_network_set_path(struct connman_network *network, const char *path)
325 {
326         g_free(network->element.devpath);
327         network->element.devpath = g_strdup(path);
328
329         g_free(network->path);
330         network->path = g_strdup(path);
331 }
332
333 /**
334  * connman_network_get_path:
335  * @network: network structure
336  *
337  * Get path name of network
338  */
339 const char *connman_network_get_path(struct connman_network *network)
340 {
341         return network->path;
342 }
343
344 /**
345  * connman_network_set_index:
346  * @network: network structure
347  * @index: index number
348  *
349  * Set index number of network
350  */
351 void connman_network_set_index(struct connman_network *network, int index)
352 {
353         network->element.index = index;
354 }
355
356 /**
357  * connman_network_get_index:
358  * @network: network structure
359  *
360  * Get index number of network
361  */
362 int connman_network_get_index(struct connman_network *network)
363 {
364         return network->element.index;
365 }
366
367 /**
368  * connman_network_set_connected:
369  * @network: network structure
370  * @connected: connected state
371  *
372  * Change connected state of network
373  */
374 int connman_network_set_connected(struct connman_network *network,
375                                                 connman_bool_t connected)
376 {
377         DBG("network %p connected %d", network, connected);
378
379         if (network->connected == connected)
380                 return -EALREADY;
381
382         network->connected = connected;
383
384         if (connected == TRUE) {
385                 struct connman_element *element;
386
387                 element = connman_element_create(NULL);
388                 if (element != NULL) {
389                         element->type    = CONNMAN_ELEMENT_TYPE_DEVICE;
390                         element->subtype = CONNMAN_ELEMENT_SUBTYPE_NETWORK;
391                         element->index   = network->element.index;
392
393                         if (connman_element_register(element,
394                                                         &network->element) < 0)
395                                 connman_element_unref(element);
396                 }
397         } else
398                 connman_element_unregister_children(&network->element);
399
400         return 0;
401 }
402
403 void __connman_network_set_device(struct connman_network *network,
404                                         struct connman_device *device)
405 {
406         network->device = device;
407 }
408
409 /**
410  * connman_network_get_device:
411  * @network: network structure
412  *
413  * Get parent device of network
414  */
415 struct connman_device *connman_network_get_device(struct connman_network *network)
416 {
417         return network->device;
418 }
419
420 /**
421  * connman_network_get_data:
422  * @network: network structure
423  *
424  * Get private network data pointer
425  */
426 void *connman_network_get_data(struct connman_network *network)
427 {
428         return network->driver_data;
429 }
430
431 /**
432  * connman_network_set_data:
433  * @network: network structure
434  * @data: data pointer
435  *
436  * Set private network data pointer
437  */
438 void connman_network_set_data(struct connman_network *network, void *data)
439 {
440         network->driver_data = data;
441 }
442
443 static gboolean match_driver(struct connman_network *network,
444                                         struct connman_network_driver *driver)
445 {
446         if (network->type == driver->type ||
447                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
448                 return TRUE;
449
450         return FALSE;
451 }
452
453 static int network_probe(struct connman_element *element)
454 {
455         struct connman_network *network = element->network;
456         GSList *list;
457         int err;
458
459         DBG("element %p name %s", element, element->name);
460
461         if (network == NULL)
462                 return -ENODEV;
463
464         for (list = driver_list; list; list = list->next) {
465                 struct connman_network_driver *driver = list->data;
466
467                 if (match_driver(network, driver) == FALSE)
468                         continue;
469
470                 DBG("driver %p name %s", driver, driver->name);
471
472                 if (driver->probe(network) == 0) {
473                         network->driver = driver;
474                         break;
475                 }
476         }
477
478         if (network->driver == NULL)
479                 return -ENODEV;
480
481         err = register_interface(element);
482         if (err < 0) {
483                 if (network->driver->remove)
484                         network->driver->remove(network);
485                 return err;
486         }
487
488         return 0;
489 }
490
491 static void network_remove(struct connman_element *element)
492 {
493         struct connman_network *network = element->network;
494
495         DBG("element %p name %s", element, element->name);
496
497         if (network == NULL)
498                 return;
499
500         if (network->driver == NULL)
501                 return;
502
503         unregister_interface(element);
504
505         if (network->driver->remove)
506                 network->driver->remove(network);
507 }
508
509 static struct connman_driver network_driver = {
510         .name           = "network",
511         .type           = CONNMAN_ELEMENT_TYPE_NETWORK,
512         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
513         .probe          = network_probe,
514         .remove         = network_remove,
515 };
516
517 int __connman_network_init(void)
518 {
519         DBG("");
520
521         connection = connman_dbus_get_connection();
522
523         return connman_driver_register(&network_driver);
524 }
525
526 void __connman_network_cleanup(void)
527 {
528         DBG("");
529
530         connman_driver_unregister(&network_driver);
531
532         dbus_connection_unref(connection);
533 }