static void set_provider_state(struct connection_data *data) { enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN; int err = 0; if (g_str_equal(data->state, "ready") == TRUE) { state = CONNMAN_PROVIDER_STATE_READY; goto set; } else if (g_str_equal(data->state, "configuration") == TRUE) { state = CONNMAN_PROVIDER_STATE_CONNECT; } else if (g_str_equal(data->state, "idle") == TRUE) { state = CONNMAN_PROVIDER_STATE_IDLE; } else if (g_str_equal(data->state, "disconnect") == TRUE) { err = ECONNREFUSED; state = CONNMAN_PROVIDER_STATE_DISCONNECT; goto set; } else if (g_str_equal(data->state, "failure") == TRUE) { err = ECONNREFUSED; state = CONNMAN_PROVIDER_STATE_FAILURE; goto set; } connman_provider_set_state(data->provider, state); return; set: if (data->cb_data != NULL) data->cb_data->callback(data->cb_data->message, err, data->ident); connman_provider_set_state(data->provider, state); free_config_cb_data(data->cb_data); data->cb_data = NULL; }
static void vpn_newlink(unsigned flags, unsigned change, void *user_data) { struct connman_provider *provider = user_data; struct vpn_data *data = connman_provider_get_data(provider); if ((data->flags & IFF_UP) != (flags & IFF_UP)) { if (flags & IFF_UP) { data->state = VPN_STATE_READY; connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_READY); } } data->flags = flags; }
void vpn_died(struct connman_task *task, int exit_code, void *user_data) { struct connman_provider *provider = user_data; struct vpn_data *data = connman_provider_get_data(provider); int state = VPN_STATE_FAILURE; enum connman_provider_error ret; DBG("provider %p data %p", provider, data); if (data == NULL) goto vpn_exit; state = data->state; stop_vpn(provider); connman_provider_set_data(provider, NULL); connman_rtnl_remove_watch(data->watch); vpn_exit: if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT) { const char *name; struct vpn_driver_data *vpn_data = NULL; name = connman_provider_get_driver_name(provider); if (name != NULL) vpn_data = g_hash_table_lookup(driver_hash, name); if (vpn_data != NULL && vpn_data->vpn_driver->error_code != NULL) ret = vpn_data->vpn_driver->error_code(exit_code); else ret = CONNMAN_PROVIDER_ERROR_UNKNOWN; connman_provider_indicate_error(provider, ret); } else connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_IDLE); connman_provider_set_index(provider, -1); connman_provider_unref(data->provider); g_free(data->if_name); g_free(data); connman_task_destroy(task); }
static DBusMessage *vpn_notify(struct connman_task *task, DBusMessage *msg, void *user_data) { struct connman_provider *provider = user_data; struct vpn_data *data; struct vpn_driver_data *vpn_driver_data; const char *name; int state, index; data = connman_provider_get_data(provider); name = connman_provider_get_driver_name(provider); if (name == NULL) return NULL; vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data == NULL) return NULL; state = vpn_driver_data->vpn_driver->notify(msg, provider); switch (state) { case VPN_STATE_CONNECT: case VPN_STATE_READY: index = connman_provider_get_index(provider); data->watch = connman_rtnl_add_newlink_watch(index, vpn_newlink, provider); connman_inet_ifup(index); break; case VPN_STATE_UNKNOWN: case VPN_STATE_IDLE: case VPN_STATE_DISCONNECT: case VPN_STATE_FAILURE: connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_DISCONNECT); break; case VPN_STATE_AUTH_FAILURE: connman_provider_indicate_error(provider, CONNMAN_PROVIDER_ERROR_AUTH_FAILED); break; } return NULL; }
static int disconnect_provider(struct connection_data *data) { DBusPendingCall *call; DBusMessage *message; DBG("data %p path %s", data, data->path); message = dbus_message_new_method_call(VPN_SERVICE, data->path, VPN_CONNECTION_INTERFACE, VPN_DISCONNECT); if (message == NULL) return -ENOMEM; if (dbus_connection_send_with_reply(connection, message, &call, DBUS_TIMEOUT) == FALSE) { connman_error("Unable to call %s.%s()", VPN_CONNECTION_INTERFACE, VPN_DISCONNECT); dbus_message_unref(message); return -EINVAL; } if (call == NULL) { dbus_message_unref(message); return -EINVAL; } dbus_pending_call_set_notify(call, disconnect_reply, NULL, NULL); dbus_message_unref(message); connman_provider_set_state(data->provider, CONNMAN_PROVIDER_STATE_DISCONNECT); /* * We return 0 here instead of -EINPROGRESS because * __connman_service_disconnect() needs to return something * to gdbus so that gdbus will not call Disconnect() more * than once. This way we do not need to pass the dbus reply * message around the code. */ return 0; }