*
* Connection Manager
*
- * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
+ * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
return "bluetooth";
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
return "cellular";
}
network->registered = FALSE;
- emit_networks_signal(network->device);
+ if (network->device != NULL)
+ emit_networks_signal(network->device);
g_dbus_unregister_interface(connection, element->path,
CONNMAN_NETWORK_INTERFACE);
connman_ipconfig_unref(network->ipconfig);
network->ipconfig = NULL;
}
+
+ network->device = NULL;
}
/**
*/
void connman_network_set_index(struct connman_network *network, int index)
{
+ struct connman_service *service;
+
+ service = __connman_service_lookup_from_network(network);
+ if (service == NULL)
+ goto done;
+
+ if (network->element.index < 0)
+ /*
+ * This is needed for plugins that havent set their ipconfig
+ * layer yet, due to not being able to get a network index
+ * prior to creating a service.
+ */
+ __connman_service_create_ipconfig(service, index);
+ else {
+ struct connman_ipconfig *ipconfig;
+
+ /* If index changed, the index of ipconfig must be reset. */
+ ipconfig = __connman_service_get_ipconfig(service);
+ if (ipconfig == NULL)
+ goto done;
+
+ __connman_ipconfig_set_index(ipconfig, index);
+ }
+
+done:
network->element.index = index;
}
case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
case CONNMAN_NETWORK_TYPE_WIFI:
case CONNMAN_NETWORK_TYPE_WIMAX:
break;
case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
case CONNMAN_NETWORK_TYPE_WIMAX:
break;
case CONNMAN_NETWORK_TYPE_WIFI:
CONNMAN_SERVICE_STATE_FAILURE);
}
+static void set_configure_error(struct connman_network *network)
+{
+ struct connman_service *service;
+
+ network->connecting = FALSE;
+
+ service = __connman_service_lookup_from_network(network);
+
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_FAILURE);
+}
+
+void connman_network_set_method(struct connman_network *network,
+ enum connman_ipconfig_method method)
+{
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+
+ network->element.ipv4.method = method;
+
+ service = __connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return;
+
+ ipconfig = __connman_service_get_ipconfig(service);
+ if (ipconfig == NULL)
+ return;
+
+ connman_ipconfig_set_method(ipconfig, method);
+}
+
void connman_network_set_error(struct connman_network *network,
enum connman_network_error error)
{
case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
set_associate_error(network);
break;
+ case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
+ set_configure_error(network);
+ break;
}
}
-static gboolean set_connected(gpointer user_data)
+static void set_configuration(struct connman_network *network)
{
- struct connman_network *network = user_data;
struct connman_service *service;
+ DBG("network %p", network);
+
+ __connman_device_increase_connections(network->device);
+
+ __connman_device_set_network(network->device, network);
+
+ connman_device_set_disconnected(network->device, FALSE);
+
service = __connman_service_lookup_from_network(network);
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_CONFIGURATION);
+}
- if (network->connected == TRUE) {
- struct connman_element *element;
- enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
-
- switch (network->protocol) {
- case CONNMAN_NETWORK_PROTOCOL_UNKNOWN:
- return 0;
- case CONNMAN_NETWORK_PROTOCOL_IP:
- type = CONNMAN_ELEMENT_TYPE_DHCP;
- break;
- }
+static void set_connected_manual(struct connman_network *network)
+{
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+ const char *nameserver = NULL;
+ int err;
- __connman_device_increase_connections(network->device);
+ DBG("network %p", network);
- __connman_device_set_network(network->device, network);
+ service = __connman_service_lookup_from_network(network);
- connman_device_set_disconnected(network->device, FALSE);
+ ipconfig = __connman_service_get_ipconfig(service);
- if (network->element.ipv4.method ==
- CONNMAN_IPCONFIG_METHOD_MANUAL) {
- network->connecting = FALSE;
+ set_configuration(network);
- connman_network_set_associating(network, FALSE);
+ err = __connman_ipconfig_set_address(ipconfig);
+ if (err < 0) {
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
+ return;
+ }
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_READY);
+ connman_element_get_value(&network->element,
+ CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
+ if (nameserver != NULL)
+ __connman_service_append_nameserver(service, nameserver);
- return TRUE;
- }
+ __connman_ipconfig_set_gateway(ipconfig, &network->element);
+
+ network->connecting = FALSE;
- element = connman_element_create(NULL);
- if (element != NULL) {
- element->type = type;
- element->index = network->element.index;
+ connman_network_set_associating(network, FALSE);
- if (connman_element_register(element,
- &network->element) < 0)
- connman_element_unref(element);
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
+}
- __connman_service_indicate_state(service,
- CONNMAN_SERVICE_STATE_CONFIGURATION);
+static int set_connected_dhcp(struct connman_network *network)
+{
+ struct connman_element *element;
+ int error;
+
+ DBG("network %p", network);
+
+ if (network->protocol != CONNMAN_NETWORK_PROTOCOL_IP)
+ return -EINVAL;
+
+ element = connman_element_create(NULL);
+ if (element == NULL)
+ return -ENOMEM;
+
+ element->type = CONNMAN_ELEMENT_TYPE_DHCP;
+ element->index = network->element.index;
+
+ error = connman_element_register(element, &network->element);
+ if (error < 0) {
+ connman_element_unref(element);
+ return error;
+ }
+
+ set_configuration(network);
+
+ return 0;
+}
+
+static gboolean set_connected(gpointer user_data)
+{
+ struct connman_network *network = user_data;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig;
+ enum connman_ipconfig_method method;
+
+ service = __connman_service_lookup_from_network(network);
+
+ ipconfig = __connman_service_get_ipconfig(service);
+
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ DBG("method %d", method);
+
+ if (network->connected == TRUE) {
+ switch (method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ return FALSE;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ set_connected_manual(network);
+ return TRUE;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ if (set_connected_dhcp(network) < 0) {
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ return FALSE;
+ }
}
+
} else {
+ struct connman_service *service;
+
connman_element_unregister_children(&network->element);
__connman_device_set_network(network->device, NULL);
__connman_device_decrease_connections(network->device);
+ service = __connman_service_lookup_from_network(network);
+
__connman_service_indicate_state(service,
CONNMAN_SERVICE_STATE_IDLE);
}
if (err < 0) {
if (err == -EINPROGRESS)
connman_network_set_associating(network, TRUE);
- else
+ else {
+ network->connecting = FALSE;
network->hidden = FALSE;
+ }
return err;
}
err = network->driver->disconnect(network);
if (err == 0) {
- network->connected = FALSE;
+ connman_network_set_connected(network, FALSE);
set_connected(network);
}
return err;
}
+static int dhcp_start(struct connman_network *network)
+{
+ struct connman_element *element;
+ int error;
+
+ if (network->protocol != CONNMAN_NETWORK_PROTOCOL_IP)
+ return -EINVAL;
+
+ element = connman_element_create(NULL);
+ if (element == NULL)
+ return -ENOMEM;
+
+ element->type = CONNMAN_ELEMENT_TYPE_DHCP;
+ element->index = network->element.index;
+
+ error = connman_element_register(element, &network->element);
+ if (error < 0) {
+ connman_element_unref(element);
+ return error;
+ }
+
+ return 0;
+}
+
+static int dhcp_stop(struct connman_network *network)
+{
+ if (network->protocol != CONNMAN_NETWORK_PROTOCOL_IP)
+ return -EINVAL;
+
+ connman_element_unregister_children_type(&network->element,
+ CONNMAN_ELEMENT_TYPE_CONNECTION);
+ connman_element_unregister_children_type(&network->element,
+ CONNMAN_ELEMENT_TYPE_IPV4);
+ connman_element_unregister_children_type(&network->element,
+ CONNMAN_ELEMENT_TYPE_DHCP);
+
+ return 0;
+}
+
+static int manual_ipv4_set(struct connman_network *network,
+ struct connman_ipconfig *ipconfig)
+{
+ struct connman_service *service;
+ int err;
+
+ service = __connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return -EINVAL;
+
+ err = __connman_ipconfig_set_address(ipconfig);
+ if (err < 0) {
+ connman_network_set_error(network,
+ CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
+ return err;
+ }
+
+ __connman_ipconfig_set_gateway(ipconfig, &network->element);
+
+ __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY);
+
+ return 0;
+}
+
+int __connman_network_clear_ipconfig(struct connman_network *network,
+ struct connman_ipconfig *ipconfig)
+{
+ struct connman_service *service;
+ enum connman_ipconfig_method method;
+
+ service = __connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return -EINVAL;
+
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ switch (method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ return -EINVAL;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ connman_element_unregister_children_type(&network->element,
+ CONNMAN_ELEMENT_TYPE_CONNECTION);
+ __connman_ipconfig_clear_address(ipconfig);
+ break;
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ dhcp_stop(network);
+ break;
+ }
+
+ __connman_service_indicate_state(service,
+ CONNMAN_SERVICE_STATE_CONFIGURATION);
+
+ return 0;
+}
+
+int __connman_network_set_ipconfig(struct connman_network *network, struct connman_ipconfig *ipconfig)
+{
+ enum connman_ipconfig_method method;
+
+ method = __connman_ipconfig_get_method(ipconfig);
+
+ switch (method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ return -EINVAL;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ return manual_ipv4_set(network, ipconfig);
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ return dhcp_start(network);
+ }
+
+ return 0;
+}
+
/**
* connman_network_set_address:
* @network: network structure
int connman_network_set_string(struct connman_network *network,
const char *key, const char *value)
{
+ int err;
+
DBG("network %p key %s value %s", network, key, value);
if (g_strcmp0(key, "Name") == 0)
network->wifi.phase2_auth = g_strdup(value);
}
- return connman_element_set_string(&network->element, key, value);
+ err = connman_element_set_string(&network->element, key, value);
+ if (err < 0)
+ return err;
+
+ if (network->driver == NULL)
+ return 0;
+
+ if (network->driver->setup)
+ return network->driver->setup(network, key);
+
+ return 0;
}
/**
case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
case CONNMAN_NETWORK_TYPE_WIFI:
case CONNMAN_NETWORK_TYPE_WIMAX:
if (network->group != NULL)
case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
case CONNMAN_NETWORK_TYPE_CELLULAR:
- case CONNMAN_NETWORK_TYPE_MBM:
- case CONNMAN_NETWORK_TYPE_HSO:
case CONNMAN_NETWORK_TYPE_WIFI:
case CONNMAN_NETWORK_TYPE_WIMAX:
if (network->group != NULL) {