Exemple #1
0
static int set_string(struct connman_provider *provider,
					const char *key, const char *value)
{
	struct connection_data *data;

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return -EINVAL;

	DBG("data %p provider %p key %s value %s", data, provider, key, value);

	if (g_str_equal(key, "Type") == TRUE) {
		g_free(data->type);
		data->type = g_strdup(value);
	} else if (g_str_equal(key, "Name") == TRUE) {
		g_free(data->name);
		data->name = g_strdup(value);
	} else if (g_str_equal(key, "Host") == TRUE) {
		g_free(data->host);
		data->host = g_strdup(value);
	} else if (g_str_equal(key, "VPN.Domain") == TRUE ||
				g_str_equal(key, "Domain") == TRUE) {
		g_free(data->domain);
		data->domain = g_strdup(value);
	} else
		g_hash_table_replace(data->setting_strings,
				g_strdup(key), g_strdup(value));
	return 0;
}
Exemple #2
0
static const char *get_string(struct connman_provider *provider,
							const char *key)
{
	struct connection_data *data;

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return NULL;

	DBG("data %p provider %p key %s", data, provider, key);

	if (g_str_equal(key, "Type") == TRUE)
		return data->type;
	else if (g_str_equal(key, "Name") == TRUE)
		return data->name;
	else if (g_str_equal(key, "Host") == TRUE)
		return data->host;
	else if (g_str_equal(key, "HostIP") == TRUE) {
		if (data->host_ip == NULL ||
				data->host_ip[0] == NULL)
			return data->host;
		else
			return data->host_ip[0];
	} else if (g_str_equal(key, "VPN.Domain") == TRUE)
		return data->domain;

	return g_hash_table_lookup(data->setting_strings, key);
}
Exemple #3
0
static int set_routes(struct connman_provider *provider,
				enum connman_provider_route_type type)
{
	struct connection_data *data;
	GHashTableIter iter;
	gpointer value, key;

	DBG("provider %p", provider);

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return -EINVAL;

	if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
					type == CONNMAN_PROVIDER_ROUTE_USER) {
		g_hash_table_iter_init(&iter, data->user_routes);

		while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
			set_route(data, value);
	}

	if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
				type == CONNMAN_PROVIDER_ROUTE_SERVER) {
		g_hash_table_iter_init(&iter, data->server_routes);

		while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
			set_route(data, value);
	}

	return 0;
}
Exemple #4
0
static int vpn_disconnect(struct connman_provider *provider)
{
    struct vpn_data *data = connman_provider_get_data(provider);
    struct vpn_driver_data *vpn_driver_data;
    const char *name;

    DBG("disconnect provider %p:", provider);

    if (data == NULL)
        return 0;

    name = connman_provider_get_driver_name(provider);
    if (name == NULL)
        return 0;

    vpn_driver_data = g_hash_table_lookup(driver_hash, name);
    if (vpn_driver_data->vpn_driver->disconnect)
        vpn_driver_data->vpn_driver->disconnect();

    if (data->watch != 0)
        connman_rtnl_remove_watch(data->watch);

    data->watch = 0;
    data->state = VPN_STATE_DISCONNECT;
    connman_task_stop(data->task);

    return 0;
}
Exemple #5
0
static int provider_connect(struct connman_provider *provider)
{
	struct connection_data *data;

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return -EINVAL;

	return connect_provider(data, NULL);
}
Exemple #6
0
static int stop_vpn(struct connman_provider *provider)
{
    struct vpn_data *data = connman_provider_get_data(provider);
    struct vpn_driver_data *vpn_driver_data;
    const char *name;
    struct ifreq ifr;
    int fd, err;

    if (data == NULL)
        return -EINVAL;

    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)
        return 0;

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
    sprintf(ifr.ifr_name, "%s", data->if_name);

    fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
    if (fd < 0) {
        err = -errno;
        connman_error("Failed to open /dev/net/tun to device %s: %s",
                      data->if_name, strerror(errno));
        return err;
    }

    if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
        err = -errno;
        connman_error("Failed to TUNSETIFF for device %s to it: %s",
                      data->if_name, strerror(errno));
        close(fd);
        return err;
    }

    if (ioctl(fd, TUNSETPERSIST, 0)) {
        err = -errno;
        connman_error("Failed to set tun device %s nonpersistent: %s",
                      data->if_name, strerror(errno));
        close(fd);
        return err;
    }
    close(fd);
    DBG("Killed tun device %s", data->if_name);
    return 0;
}
Exemple #7
0
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;
}
Exemple #8
0
static int provider_disconnect(struct connman_provider *provider)
{
	struct connection_data *data;

	DBG("provider %p", provider);

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return -EINVAL;

	if (g_str_equal(data->state, "ready") == TRUE ||
			g_str_equal(data->state, "configuration") == TRUE)
		return disconnect_provider(data);

	return 0;
}
Exemple #9
0
static int provider_remove(struct connman_provider *provider)
{
	DBusPendingCall *call;
	DBusMessage *message;
	struct connection_data *data;

	data = connman_provider_get_data(provider);

	DBG("provider %p data %p", provider, data);

	/*
	 * When provider.c:provider_remove() calls this function,
	 * it will remove the provider itself after the call.
	 * This means that we cannot use the provider pointer later
	 * as it is no longer valid.
	 */
	data->provider = NULL;

	message = dbus_message_new_method_call(VPN_SERVICE, "/",
					VPN_MANAGER_INTERFACE,
					VPN_REMOVE);
	if (message == NULL)
		return -ENOMEM;

	dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &data->path,
				NULL);

	if (dbus_connection_send_with_reply(connection, message,
					&call, DBUS_TIMEOUT) == FALSE) {
		connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
							VPN_REMOVE);
		dbus_message_unref(message);
		return -EINVAL;
	}

	if (call == NULL) {
		dbus_message_unref(message);
		return -EINVAL;
	}

	dbus_pending_call_set_notify(call, remove_connection_reply,
							NULL, NULL);

	dbus_message_unref(message);

	return 0;
}
Exemple #10
0
static int vpn_remove(struct connman_provider *provider)
{
    struct vpn_data *data;

    data = connman_provider_get_data(provider);
    if (data == NULL)
        return 0;

    if (data->watch != 0)
        connman_rtnl_remove_watch(data->watch);
    data->watch = 0;
    connman_task_stop(data->task);

    g_usleep(G_USEC_PER_SEC);
    stop_vpn(provider);
    return 0;
}
Exemple #11
0
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);
}
Exemple #12
0
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;
}
Exemple #13
0
static connman_bool_t check_routes(struct connman_provider *provider)
{
	struct connection_data *data;

	DBG("provider %p", provider);

	data = connman_provider_get_data(provider);
	if (data == NULL)
		return FALSE;

	if (data->user_routes != NULL &&
			g_hash_table_size(data->user_routes) > 0)
		return TRUE;

	if (data->server_routes != NULL &&
			g_hash_table_size(data->server_routes) > 0)
		return TRUE;

	return FALSE;
}
Exemple #14
0
int vpn_set_ifname(struct connman_provider *provider, const char *ifname)
{
    struct vpn_data *data = connman_provider_get_data(provider);
    int index;

    if (ifname == NULL || data == NULL)
        return  -EIO;

    index = connman_inet_ifindex(ifname);
    if (index < 0)
        return  -EIO;

    if (data->if_name != NULL)
        g_free(data->if_name);

    data->if_name = (char *)g_strdup(ifname);
    connman_provider_set_index(provider, index);

    return 0;
}
Exemple #15
0
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;
}
Exemple #16
0
static int vpn_create_tun(struct connman_provider *provider)
{
    struct vpn_data *data = connman_provider_get_data(provider);
    struct ifreq ifr;
    int i, fd, index;
    int ret = 0;

    if (data == NULL)
        return -EISCONN;

    fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
    if (fd < 0) {
        i = -errno;
        connman_error("Failed to open /dev/net/tun: %s",
                      strerror(errno));
        ret = i;
        goto exist_err;
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;

    for (i = 0; i < 256; i++) {
        sprintf(ifr.ifr_name, "vpn%d", i);

        if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
            break;
    }

    if (i == 256) {
        connman_error("Failed to find available tun device");
        close(fd);
        ret = -ENODEV;
        goto exist_err;
    }

    data->if_name = (char *)g_strdup(ifr.ifr_name);
    if (data->if_name == NULL) {
        connman_error("Failed to allocate memory");
        close(fd);
        ret = -ENOMEM;
        goto exist_err;
    }

    if (ioctl(fd, TUNSETPERSIST, 1)) {
        i = -errno;
        connman_error("Failed to set tun persistent: %s",
                      strerror(errno));
        close(fd);
        ret = i;
        goto exist_err;
    }

    close(fd);

    index = connman_inet_ifindex(data->if_name);
    if (index < 0) {
        connman_error("Failed to get tun ifindex");
        stop_vpn(provider);
        ret = -EIO;
        goto exist_err;
    }
    connman_provider_set_index(provider, index);

    return 0;

exist_err:
    return ret;
}