static int vpn_connect(struct connman_provider *provider) { struct vpn_data *data = connman_provider_get_data(provider); struct vpn_driver_data *vpn_driver_data; const char *name; int ret = 0; if (data != NULL) return -EISCONN; data = g_try_new0(struct vpn_data, 1); if (data == NULL) return -ENOMEM; data->provider = connman_provider_ref(provider); data->watch = 0; data->flags = 0; data->task = NULL; data->state = VPN_STATE_IDLE; connman_provider_set_data(provider, data); name = connman_provider_get_driver_name(provider); if (name == NULL) return -EINVAL; vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL && vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) { ret = vpn_create_tun(provider); if (ret < 0) goto exist_err; } data->task = connman_task_create(vpn_driver_data->program); if (data->task == NULL) { ret = -ENOMEM; stop_vpn(provider); goto exist_err; } if (connman_task_set_notify(data->task, "notify", vpn_notify, provider)) { ret = -ENOMEM; stop_vpn(provider); connman_task_destroy(data->task); data->task = NULL; goto exist_err; } ret = vpn_driver_data->vpn_driver->connect(provider, data->task, data->if_name); if (ret < 0) { stop_vpn(provider); connman_task_destroy(data->task); data->task = NULL; goto exist_err; } DBG("%s started with dev %s", vpn_driver_data->provider_driver.name, data->if_name); data->state = VPN_STATE_CONNECT; return -EINPROGRESS; exist_err: connman_provider_set_index(provider, -1); connman_provider_set_data(provider, NULL); connman_provider_unref(data->provider); g_free(data->if_name); g_free(data); return ret; }
static int vpn_connect(struct vpn_provider *provider, vpn_provider_connect_cb_t cb, const char *dbus_sender, void *user_data) { struct vpn_data *data = vpn_provider_get_data(provider); struct vpn_driver_data *vpn_driver_data; const char *name; int ret = 0; enum vpn_state state = VPN_STATE_UNKNOWN; if (data) state = data->state; DBG("data %p state %d", data, state); switch (state) { case VPN_STATE_UNKNOWN: data = g_try_new0(struct vpn_data, 1); if (!data) return -ENOMEM; data->provider = vpn_provider_ref(provider); data->watch = 0; data->flags = 0; data->task = NULL; vpn_provider_set_data(provider, data); /* fall through */ case VPN_STATE_DISCONNECT: case VPN_STATE_IDLE: case VPN_STATE_FAILURE: case VPN_STATE_AUTH_FAILURE: data->state = VPN_STATE_IDLE; break; case VPN_STATE_CONNECT: return -EINPROGRESS; case VPN_STATE_READY: return -EISCONN; } name = vpn_provider_get_driver_name(provider); if (!name) return -EINVAL; vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (!vpn_driver_data || !vpn_driver_data->vpn_driver) { ret = -EINVAL; goto exist_err; } if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) { ret = vpn_create_tun(provider); if (ret < 0) goto exist_err; } data->task = connman_task_create(vpn_driver_data->program); if (!data->task) { ret = -ENOMEM; stop_vpn(provider); goto exist_err; } if (connman_task_set_notify(data->task, "notify", vpn_notify, provider)) { ret = -ENOMEM; stop_vpn(provider); connman_task_destroy(data->task); data->task = NULL; goto exist_err; } ret = vpn_driver_data->vpn_driver->connect(provider, data->task, data->if_name, cb, dbus_sender, user_data); if (ret < 0 && ret != -EINPROGRESS) { stop_vpn(provider); connman_task_destroy(data->task); data->task = NULL; goto exist_err; } DBG("%s started with dev %s", vpn_driver_data->provider_driver.name, data->if_name); data->state = VPN_STATE_CONNECT; return -EINPROGRESS; exist_err: vpn_provider_set_index(provider, -1); vpn_provider_set_data(provider, NULL); vpn_provider_unref(data->provider); g_free(data->if_name); g_free(data); return ret; }