static gboolean set_connected(gpointer user_data) { struct connman_network *network = user_data; struct connman_service *service; service = __connman_service_lookup_from_network(network); 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: connman_warn("%s: unknown protocol", __func__); return 0; case CONNMAN_NETWORK_PROTOCOL_IP: type = CONNMAN_ELEMENT_TYPE_DHCP; break; case CONNMAN_NETWORK_PROTOCOL_PPP: type = CONNMAN_ELEMENT_TYPE_PPP; break; } __connman_device_increase_connections(network->device); __connman_device_set_network(network->device, network); connman_device_set_disconnected(network->device, FALSE); element = connman_element_create(NULL); if (element != NULL) { element->type = type; element->index = network->element.index; if (connman_element_register(element, &network->element) < 0) connman_element_unref(element); __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_CONFIGURATION); } } else { connman_element_unregister_children(&network->element); __connman_device_set_network(network->device, NULL); network->hidden = FALSE; __connman_device_decrease_connections(network->device); __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE); } network->connecting = FALSE; connman_network_set_associating(network, FALSE); return FALSE; }
static int pan_disconnect(struct connman_network *network) { const char *path = connman_network_get_string(network, "Path"); DBusMessage *message; DBusPendingCall *call; DBG("network %p", network); if (!path) return -EINVAL; message = dbus_message_new_method_call(BLUEZ_SERVICE, path, BLUEZ_NETWORK_INTERFACE, DISCONNECT); if (!message) return -ENOMEM; dbus_message_set_auto_start(message, FALSE); dbus_message_append_args(message, DBUS_TYPE_INVALID); if (!dbus_connection_send_with_reply(connection, message, &call, TIMEOUT)) { connman_error("Failed to disconnect service"); dbus_message_unref(message); return -EINVAL; } if (!call) { connman_error("D-Bus connection not available"); dbus_message_unref(message); return -EINVAL; } connman_network_ref(network); connman_network_set_associating(network, false); dbus_pending_call_set_notify(call, disconnect_reply, g_strdup(path), g_free); dbus_message_unref(message); return 0; }
/** * __connman_network_connect: * @network: network structure * * Connect network */ int __connman_network_connect(struct connman_network *network) { int err; DBG("network %p", network); if (network->connected == TRUE) return -EISCONN; if (network->connecting == TRUE || network->associating == TRUE) return -EALREADY; if (network->driver == NULL) return -EUNATCH; if (network->driver->connect == NULL) return -ENOSYS; if (network->device == NULL) return -ENODEV; network->connecting = TRUE; #if defined TIZEN_EXT if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR) #endif __connman_device_disconnect(network->device); err = network->driver->connect(network); if (err < 0) { if (err == -EINPROGRESS) connman_network_set_associating(network, TRUE); else { network->connecting = FALSE; } return err; } network->connected = TRUE; set_connected(network); return err; }
static void set_connected_manual(struct connman_network *network) { struct connman_service *service; struct connman_ipconfig *ipconfig; int err; DBG("network %p", network); service = __connman_service_lookup_from_network(network); ipconfig = __connman_service_get_ip4config(service); if (__connman_ipconfig_get_local(ipconfig) == NULL) __connman_service_read_ip4config(service); set_configuration(network); err = __connman_ipconfig_address_add(ipconfig); if (err < 0) goto err; #if defined TIZEN_EXT /* * Description: __connman_service_lookup_from_index cannot find correct service */ err = __connman_ipconfig_gateway_add(ipconfig, service); #else err = __connman_ipconfig_gateway_add(ipconfig); #endif if (err < 0) goto err; network->connecting = FALSE; connman_network_set_associating(network, FALSE); return; err: connman_network_set_error(network, CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); return; }
static int set_connected_fixed(struct connman_network *network) { struct connman_service *service; struct connman_ipconfig *ipconfig_ipv4; int err; DBG(""); service = __connman_service_lookup_from_network(network); ipconfig_ipv4 = __connman_service_get_ip4config(service); set_configuration(network); network->connecting = FALSE; connman_network_set_associating(network, FALSE); err = __connman_ipconfig_address_add(ipconfig_ipv4); if (err < 0) goto err; #if defined TIZEN_EXT /* * Description: __connman_service_lookup_from_index cannot find correct service */ err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service); #else err = __connman_ipconfig_gateway_add(ipconfig_ipv4); #endif if (err < 0) goto err; return 0; err: connman_network_set_error(network, CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); return err; }
static int bluetooth_pan_connect(struct connman_network *network) { struct bluetooth_pan *pan = connman_network_get_data(network); const char *path; DBG("network %p", network); if (!pan) return -EINVAL; path = g_dbus_proxy_get_path(pan->btnetwork_proxy); if (!g_dbus_proxy_method_call(pan->btnetwork_proxy, "Connect", pan_connect_append, pan_connect_cb, g_strdup(path), g_free)) return -EIO; connman_network_set_associating(pan->network, true); return -EINPROGRESS; }
/** * __connman_network_connect: * @network: network structure * * Connect network */ int __connman_network_connect(struct connman_network *network) { int err; _DBG_NETWORK("network %p", network); if (network->connected == TRUE) return -EISCONN; if (network->connecting == TRUE || network->associating == TRUE) return -EALREADY; if (network->driver == NULL) return -EUNATCH; if (network->driver->connect == NULL) return -ENOSYS; __connman_device_disconnect(network->device); network->connecting = TRUE; err = network->driver->connect(network); if (err < 0) { if (err == -EINPROGRESS) connman_network_set_associating(network, TRUE); else network->hidden = FALSE; return err; } network->connected = TRUE; set_connected(network); return err; }
static void pan_connect_cb(DBusMessage *message, void *user_data) { const char *path = user_data; const char *iface = NULL; struct bluetooth_pan *pan; DBusMessageIter iter; pan = g_hash_table_lookup(networks, path); if (!pan || !pan->network) { DBG("network already removed"); return; } if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) { const char *dbus_error = dbus_message_get_error_name(message); DBG("network %p %s", pan->network, dbus_error); if (strcmp(dbus_error, "org.bluez.Error.AlreadyConnected") != 0) { connman_network_set_associating(pan->network, false); connman_network_set_error(pan->network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return; } } else { if (dbus_message_iter_init(message, &iter) && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&iter, &iface); } DBG("network %p interface %s", pan->network, iface); pan_connect(pan, iface); }
static gboolean network_changed(DBusConnection *conn, DBusMessage *message, void *user_data) { const char *path = dbus_message_get_path(message); struct connman_network *network; DBusMessageIter iter, value; const char *key; DBG("path %s", path); network = g_hash_table_lookup(bluetooth_networks, path); if (network == NULL) return TRUE; if (dbus_message_iter_init(message, &iter) == FALSE) return TRUE; dbus_message_iter_get_basic(&iter, &key); dbus_message_iter_next(&iter); dbus_message_iter_recurse(&iter, &value); if (g_str_equal(key, "Connected") == TRUE) { dbus_bool_t connected; dbus_message_iter_get_basic(&value, &connected); if (connected == TRUE) return TRUE; connman_network_set_associating(network, FALSE); connman_network_set_connected(network, FALSE); } return TRUE; }
static void state_change(struct supplicant_task *task, DBusMessage *msg) { DBusError error; const char *newstate, *oldstate; unsigned char bssid[ETH_ALEN]; unsigned int bssid_len; enum supplicant_state state, ostate; dbus_error_init(&error); if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &newstate, DBUS_TYPE_STRING, &oldstate, DBUS_TYPE_INVALID) == FALSE) { if (dbus_error_is_set(&error) == TRUE) { connman_error("%s", error.message); dbus_error_free(&error); } else connman_error("Wrong arguments for state change"); return; } connman_info("%s state change %s -> %s%s", task->ifname, oldstate, newstate, task->scanning == TRUE ? " (scanning)" : ""); state = string2state(newstate); if (state == WPA_INVALID) return; if (task->scanning == TRUE && state != WPA_SCANNING) { connman_device_set_scanning(task->device, FALSE); task->scanning = FALSE; } ostate = task->state; task->state = state; if (task->network == NULL) return; switch (task->state) { case WPA_COMPLETED: if (ostate != WPA_ASSOCIATED && ostate != WPA_GROUP_HANDSHAKE) goto badstate; /* reset bg scan reschedule */ connman_device_reset_scan(task->device); if (get_bssid(task->device, bssid, &bssid_len) == 0) connman_network_set_address(task->network, bssid, bssid_len); /* carrier on */ connman_network_set_connected(task->network, TRUE); break; case WPA_ASSOCIATING: if (ostate != WPA_SCANNING && ostate != WPA_COMPLETED) goto badstate; if (ostate == WPA_SCANNING) connman_network_set_associating(task->network, TRUE); break; case WPA_INACTIVE: if (ostate != WPA_SCANNING && ostate != WPA_DISCONNECTED) goto badstate; /* fall thru... */ case WPA_DISCONNECTED: /* carrier off */ connman_network_set_connected(task->network, FALSE); if (task->disconnecting == TRUE) { connman_network_unref(task->network); task->disconnecting = FALSE; if (task->pending_network != NULL) { task->network = task->pending_network; task->pending_network = NULL; task_connect(task); } else task->network = NULL; } break; default: connman_network_set_associating(task->network, FALSE); break; } return; badstate: connman_error("%s invalid state change %s -> %s%s", task->ifname, oldstate, newstate, task->scanning == TRUE ? " (scanning)" : ""); }
static gboolean set_connected(gpointer user_data) { struct connman_network *network = user_data; struct connman_service *service; struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; enum connman_ipconfig_method ipv4_method, ipv6_method; service = __connman_service_lookup_from_network(network); ipconfig_ipv4 = __connman_service_get_ip4config(service); ipconfig_ipv6 = __connman_service_get_ip6config(service); DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4, ipconfig_ipv6); ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method); DBG("network connected %d", network->connected); if (network->connected == TRUE) { int ret; switch (ipv6_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: break; case CONNMAN_IPCONFIG_METHOD_AUTO: autoconf_ipv6_set(network); break; case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: ret = manual_ipv6_set(network, ipconfig_ipv6); if (ret != 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return FALSE; } break; case CONNMAN_IPCONFIG_METHOD_DHCP: break; } switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: case CONNMAN_IPCONFIG_METHOD_AUTO: return FALSE; case CONNMAN_IPCONFIG_METHOD_FIXED: if (set_connected_fixed(network) < 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return FALSE; } return TRUE; case CONNMAN_IPCONFIG_METHOD_MANUAL: 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 { enum connman_service_state state; __connman_device_set_network(network->device, NULL); switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: case CONNMAN_IPCONFIG_METHOD_AUTO: case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: break; case CONNMAN_IPCONFIG_METHOD_DHCP: __connman_dhcp_stop(network); break; } /* * We only set the disconnect state if we were not in idle * or in failure. It does not make sense to go to disconnect * state if we were not connected. */ state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV4); if (state != CONNMAN_SERVICE_STATE_IDLE && state != CONNMAN_SERVICE_STATE_FAILURE) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV4); state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV6); if (state != CONNMAN_SERVICE_STATE_IDLE && state != CONNMAN_SERVICE_STATE_FAILURE) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV6); __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); __connman_ipconfig_address_unset(ipconfig_ipv4); __connman_ipconfig_address_unset(ipconfig_ipv6); /* * Special handling for IPv6 autoconfigured address. * The simplest way to remove autoconfigured routes is to * disable IPv6 temporarily so that kernel will do the cleanup * automagically. */ if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { __connman_ipconfig_disable_ipv6(ipconfig_ipv6); __connman_ipconfig_enable_ipv6(ipconfig_ipv6); } #if defined TIZEN_EXT if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR) { network->connecting = FALSE; connman_network_set_associating(network, FALSE); } #endif __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV6); #if defined TIZEN_EXT if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR) return FALSE; #endif } network->connecting = FALSE; connman_network_set_associating(network, FALSE); return FALSE; }