5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
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.
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.
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
32 struct connman_network {
33 struct connman_element element;
34 enum connman_network_type type;
35 enum connman_network_protocol protocol;
36 connman_bool_t connected;
37 connman_uint8_t strength;
42 struct connman_network_driver *driver;
45 struct connman_device *device;
56 static DBusMessage *get_properties(DBusConnection *conn,
57 DBusMessage *msg, void *data)
59 struct connman_network *network = data;
61 DBusMessageIter array, dict;
65 reply = dbus_message_new_method_return(msg);
69 dbus_message_iter_init_append(reply, &array);
71 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
72 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
73 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
74 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
76 if (network->device) {
77 const char *path = connman_device_get_path(network->device);
79 connman_dbus_dict_append_variant(&dict, "Device",
80 DBUS_TYPE_OBJECT_PATH, &path);
83 if (network->name != NULL)
84 connman_dbus_dict_append_variant(&dict, "Name",
85 DBUS_TYPE_STRING, &network->name);
87 connman_dbus_dict_append_variant(&dict, "Connected",
88 DBUS_TYPE_BOOLEAN, &network->connected);
90 if (network->strength > 0)
91 connman_dbus_dict_append_variant(&dict, "Strength",
92 DBUS_TYPE_BYTE, &network->strength);
94 if (network->wifi.ssid != NULL && network->wifi.ssid_len > 0)
95 connman_dbus_dict_append_array(&dict, "WiFi.SSID",
96 DBUS_TYPE_BYTE, &network->wifi.ssid,
97 network->wifi.ssid_len);
99 if (network->wifi.mode != NULL)
100 connman_dbus_dict_append_variant(&dict, "WiFi.Mode",
101 DBUS_TYPE_STRING, &network->wifi.mode);
103 if (network->wifi.security != NULL)
104 connman_dbus_dict_append_variant(&dict, "WiFi.Security",
105 DBUS_TYPE_STRING, &network->wifi.security);
107 if (network->wifi.passphrase != NULL)
108 connman_dbus_dict_append_variant(&dict, "WiFi.Passphrase",
109 DBUS_TYPE_STRING, &network->wifi.passphrase);
111 dbus_message_iter_close_container(&array, &dict);
116 static DBusMessage *set_property(DBusConnection *conn,
117 DBusMessage *msg, void *data)
119 DBusMessageIter iter, value;
122 DBG("conn %p", conn);
124 if (dbus_message_iter_init(msg, &iter) == FALSE)
125 return __connman_error_invalid_arguments(msg);
127 dbus_message_iter_get_basic(&iter, &name);
128 dbus_message_iter_next(&iter);
129 dbus_message_iter_recurse(&iter, &value);
131 if (__connman_security_check_privileges(msg) < 0)
132 return __connman_error_permission_denied(msg);
134 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
137 static DBusMessage *do_connect(DBusConnection *conn,
138 DBusMessage *msg, void *data)
140 struct connman_network *network = data;
143 DBG("conn %p", conn);
145 if (network->driver && network->driver->connect) {
146 err = network->driver->connect(network);
147 if (err < 0 && err != -EINPROGRESS)
148 return __connman_error_failed(msg);
151 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
154 static DBusMessage *do_disconnect(DBusConnection *conn,
155 DBusMessage *msg, void *data)
157 struct connman_network *network = data;
160 DBG("conn %p", conn);
162 if (network->driver && network->driver->disconnect) {
163 err = network->driver->disconnect(network);
164 if (err < 0 && err != -EINPROGRESS)
165 return __connman_error_failed(msg);
168 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
171 static GDBusMethodTable network_methods[] = {
172 { "GetProperties", "", "a{sv}", get_properties },
173 { "SetProperty", "sv", "", set_property },
174 { "Connect", "", "", do_connect },
175 { "Disconnect", "", "", do_disconnect },
179 static GDBusSignalTable network_signals[] = {
180 { "PropertyChanged", "sv" },
184 static DBusConnection *connection;
186 static void emit_networks_signal(void)
190 static int register_interface(struct connman_element *element)
192 struct connman_network *network = element->network;
194 DBG("element %p name %s", element, element->name);
196 if (g_dbus_register_interface(connection, element->path,
197 CONNMAN_NETWORK_INTERFACE,
198 network_methods, network_signals,
199 NULL, network, NULL) == FALSE) {
200 connman_error("Failed to register %s network", element->path);
204 emit_networks_signal();
209 static void unregister_interface(struct connman_element *element)
211 DBG("element %p name %s", element, element->name);
213 emit_networks_signal();
215 g_dbus_unregister_interface(connection, element->path,
216 CONNMAN_NETWORK_INTERFACE);
219 static GSList *driver_list = NULL;
221 static gint compare_priority(gconstpointer a, gconstpointer b)
223 const struct connman_network_driver *driver1 = a;
224 const struct connman_network_driver *driver2 = b;
226 return driver2->priority - driver1->priority;
230 * connman_network_driver_register:
231 * @driver: network driver definition
233 * Register a new network driver
235 * Returns: %0 on success
237 int connman_network_driver_register(struct connman_network_driver *driver)
239 DBG("driver %p name %s", driver, driver->name);
241 driver_list = g_slist_insert_sorted(driver_list, driver,
248 * connman_network_driver_unregister:
249 * @driver: network driver definition
251 * Remove a previously registered network driver
253 void connman_network_driver_unregister(struct connman_network_driver *driver)
255 DBG("driver %p name %s", driver, driver->name);
257 driver_list = g_slist_remove(driver_list, driver);
260 static void network_destruct(struct connman_element *element)
262 struct connman_network *network = element->network;
264 DBG("element %p name %s", element, element->name);
266 g_free(network->wifi.ssid);
267 g_free(network->wifi.mode);
268 g_free(network->wifi.security);
269 g_free(network->wifi.passphrase);
271 g_free(network->node);
272 g_free(network->name);
273 g_free(network->identifier);
277 * connman_network_create:
278 * @identifier: network identifier (for example an unqiue name)
280 * Allocate a new network and assign the #identifier to it.
282 * Returns: a newly-allocated #connman_network structure
284 struct connman_network *connman_network_create(const char *identifier,
285 enum connman_network_type type)
287 struct connman_network *network;
289 DBG("identifier %s type %d", identifier, type);
291 network = g_try_new0(struct connman_network, 1);
295 DBG("network %p", network);
297 network->element.refcount = 1;
299 network->element.name = g_strdup(identifier);
300 network->element.type = CONNMAN_ELEMENT_TYPE_NETWORK;
301 network->element.index = -1;
304 case CONNMAN_NETWORK_TYPE_UNKNOWN:
305 case CONNMAN_NETWORK_TYPE_VENDOR:
306 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
308 case CONNMAN_NETWORK_TYPE_WIFI:
309 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_WIFI;
311 case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
312 case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
313 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH;
315 case CONNMAN_NETWORK_TYPE_HSO:
316 network->element.subtype = CONNMAN_ELEMENT_SUBTYPE_CELLULAR;
320 network->element.network = network;
321 network->element.destruct = network_destruct;
323 network->type = type;
324 network->identifier = g_strdup(identifier);
330 * connman_network_ref:
331 * @network: network structure
333 * Increase reference counter of network
335 struct connman_network *connman_network_ref(struct connman_network *network)
337 if (connman_element_ref(&network->element) == NULL)
344 * connman_network_unref:
345 * @network: network structure
347 * Decrease reference counter of network
349 void connman_network_unref(struct connman_network *network)
351 connman_element_unref(&network->element);
355 * connman_network_get_identifier:
356 * @network: network structure
358 * Get identifier of network
360 const char *connman_network_get_identifier(struct connman_network *network)
362 return network->identifier;
366 * connman_network_get_path:
367 * @network: network structure
369 * Get path name of network
371 const char *connman_network_get_path(struct connman_network *network)
373 return network->element.path;
377 * connman_network_set_index:
378 * @network: network structure
379 * @index: index number
381 * Set index number of network
383 void connman_network_set_index(struct connman_network *network, int index)
385 network->element.index = index;
389 * connman_network_get_index:
390 * @network: network structure
392 * Get index number of network
394 int connman_network_get_index(struct connman_network *network)
396 return network->element.index;
400 * connman_network_set_protocol:
401 * @network: network structure
402 * @protocol: network protocol
404 * Change protocol of network
406 void connman_network_set_protocol(struct connman_network *network,
407 enum connman_network_protocol protocol)
409 network->protocol = protocol;
413 * connman_network_set_connected:
414 * @network: network structure
415 * @connected: connected state
417 * Change connected state of network
419 int connman_network_set_connected(struct connman_network *network,
420 connman_bool_t connected)
422 DBG("network %p connected %d", network, connected);
424 if (network->connected == connected)
427 network->connected = connected;
429 if (connected == TRUE) {
430 struct connman_element *element;
431 enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
433 switch (network->protocol) {
434 case CONNMAN_NETWORK_PROTOCOL_UNKNOWN:
436 case CONNMAN_NETWORK_PROTOCOL_IP:
437 type = CONNMAN_ELEMENT_TYPE_DHCP;
439 case CONNMAN_NETWORK_PROTOCOL_PPP:
440 type = CONNMAN_ELEMENT_TYPE_PPP;
444 element = connman_element_create(NULL);
445 if (element != NULL) {
446 element->type = type;
447 element->subtype = network->element.subtype;
448 element->index = network->element.index;
450 if (connman_element_register(element,
451 &network->element) < 0)
452 connman_element_unref(element);
455 connman_element_unregister_children(&network->element);
461 * connman_network_set_string:
462 * @network: network structure
463 * @key: unique identifier
464 * @value: string value
466 * Set string value for specific key
468 int connman_network_set_string(struct connman_network *network,
469 const char *key, const char *value)
471 DBG("network %p key %s value %s", network, key, value);
473 if (g_str_equal(key, "Name") == TRUE) {
474 g_free(network->name);
475 network->name = g_strdup(value);
476 } else if (g_str_equal(key, "Node") == TRUE) {
477 g_free(network->node);
478 network->node = g_strdup(value);
479 } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
480 g_free(network->wifi.mode);
481 network->wifi.mode = g_strdup(value);
482 } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
483 g_free(network->wifi.security);
484 network->wifi.security = g_strdup(value);
491 * connman_network_get_string:
492 * @network: network structure
493 * @key: unique identifier
495 * Get string value for specific key
497 const char *connman_network_get_string(struct connman_network *network,
500 DBG("network %p key %s", network);
502 if (g_str_equal(key, "Name") == TRUE)
503 return network->name;
504 else if (g_str_equal(key, "Node") == TRUE)
505 return network->node;
506 else if (g_str_equal(key, "WiFi.Mode") == TRUE)
507 return network->wifi.mode;
508 else if (g_str_equal(key, "WiFi.Security") == TRUE)
509 return network->wifi.security;
515 * connman_network_set_uint8:
516 * @network: network structure
517 * @key: unique identifier
518 * @value: integer value
520 * Set integer value for specific key
522 int connman_network_set_uint8(struct connman_network *network,
523 const char *key, connman_uint8_t value)
525 DBG("network %p key %s value %d", network, key, value);
527 if (g_str_equal(key, "Strength") == TRUE)
528 network->strength = value;
534 * connman_network_set_blob:
535 * @network: network structure
536 * @key: unique identifier
540 * Set binary blob value for specific key
542 int connman_network_set_blob(struct connman_network *network,
543 const char *key, const void *data, unsigned int size)
545 DBG("network %p key %s size %d", network, key, size);
547 if (g_str_equal(key, "WiFi.SSID") == TRUE) {
548 g_free(network->wifi.ssid);
549 network->wifi.ssid = g_try_malloc(size);
550 if (network->wifi.ssid != NULL) {
551 memcpy(network->wifi.ssid, data, size);
552 network->wifi.ssid_len = size;
554 network->wifi.ssid_len = 0;
560 void __connman_network_set_device(struct connman_network *network,
561 struct connman_device *device)
563 network->device = device;
567 * connman_network_get_device:
568 * @network: network structure
570 * Get parent device of network
572 struct connman_device *connman_network_get_device(struct connman_network *network)
574 return network->device;
578 * connman_network_get_data:
579 * @network: network structure
581 * Get private network data pointer
583 void *connman_network_get_data(struct connman_network *network)
585 return network->driver_data;
589 * connman_network_set_data:
590 * @network: network structure
591 * @data: data pointer
593 * Set private network data pointer
595 void connman_network_set_data(struct connman_network *network, void *data)
597 network->driver_data = data;
600 static gboolean match_driver(struct connman_network *network,
601 struct connman_network_driver *driver)
603 if (network->type == driver->type ||
604 driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
610 static int network_probe(struct connman_element *element)
612 struct connman_network *network = element->network;
616 DBG("element %p name %s", element, element->name);
621 for (list = driver_list; list; list = list->next) {
622 struct connman_network_driver *driver = list->data;
624 if (match_driver(network, driver) == FALSE)
627 DBG("driver %p name %s", driver, driver->name);
629 if (driver->probe(network) == 0) {
630 network->driver = driver;
635 if (network->driver == NULL)
638 err = register_interface(element);
640 if (network->driver->remove)
641 network->driver->remove(network);
648 static void network_remove(struct connman_element *element)
650 struct connman_network *network = element->network;
652 DBG("element %p name %s", element, element->name);
657 if (network->driver == NULL)
660 unregister_interface(element);
662 if (network->driver->remove)
663 network->driver->remove(network);
666 static struct connman_driver network_driver = {
668 .type = CONNMAN_ELEMENT_TYPE_NETWORK,
669 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
670 .probe = network_probe,
671 .remove = network_remove,
674 static int network_load(struct connman_network *network)
676 DBG("network %p", network);
681 static int network_save(struct connman_network *network)
683 DBG("network %p", network);
688 static struct connman_storage network_storage = {
690 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
691 .network_load = network_load,
692 .network_save = network_save,
695 int __connman_network_init(void)
699 connection = connman_dbus_get_connection();
701 if (connman_storage_register(&network_storage) < 0)
702 connman_error("Failed to register network storage");
704 return connman_driver_register(&network_driver);
707 void __connman_network_cleanup(void)
711 connman_driver_unregister(&network_driver);
713 connman_storage_unregister(&network_storage);
715 dbus_connection_unref(connection);