Ejemplo n.º 1
0
static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct vpn_provider *provider = data;
	DBusMessageIter iter, value;
	const char *name;
	int type;

	DBG("conn %p", conn);

	if (dbus_message_iter_init(msg, &iter) == FALSE)
		return __connman_error_invalid_arguments(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __connman_error_invalid_arguments(msg);

	dbus_message_iter_get_basic(&iter, &name);
	dbus_message_iter_next(&iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
		return __connman_error_invalid_arguments(msg);

	dbus_message_iter_recurse(&iter, &value);

	type = dbus_message_iter_get_arg_type(&value);

	if (g_str_equal(name, "UserRoutes") == TRUE) {
		GSList *networks;

		if (type != DBUS_TYPE_ARRAY)
			return __connman_error_invalid_arguments(msg);

		networks = get_user_networks(&value);
		if (networks != NULL) {
			del_routes(provider);
			provider->user_networks = networks;
			set_user_networks(provider, provider->user_networks);

			if (handle_routes == FALSE)
				provider_schedule_changed(provider,
							USER_ROUTES_CHANGED);
		}
	} else
		return __connman_error_invalid_property(msg);

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
Ejemplo n.º 2
0
static int create_configuration(DBusMessage *msg, connection_ready_cb callback)
{
	DBusMessage *new_msg = NULL;
	DBusPendingCall *call;
	DBusMessageIter iter, array, new_iter, new_dict;
	const char *type = NULL, *name = NULL;
	const char *host = NULL, *domain = NULL;
	char *ident, *me = NULL;
	int err = 0;
	dbus_bool_t result;
	struct connection_data *data;
	struct config_create_data *user_data = NULL;
	GSList *networks = NULL;

	/*
	 * We copy the old message data into new message. We cannot
	 * just use the old message as is because the user route
	 * information is not in the same format in vpnd.
	 */
	new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
	dbus_message_iter_init_append(new_msg, &new_iter);
	connman_dbus_dict_open(&new_iter, &new_dict);

	dbus_message_iter_init(msg, &iter);
	dbus_message_iter_recurse(&iter, &array);

	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
		DBusMessageIter entry, value;
		void *item_value;
		const char *key;
		int value_type;

		dbus_message_iter_recurse(&array, &entry);
		dbus_message_iter_get_basic(&entry, &key);

		dbus_message_iter_next(&entry);
		dbus_message_iter_recurse(&entry, &value);

		value_type = dbus_message_iter_get_arg_type(&value);
		item_value = NULL;

		switch (value_type) {
		case DBUS_TYPE_STRING:
			dbus_message_iter_get_basic(&value, &item_value);

			if (g_str_equal(key, "Type") == TRUE) {
				type = (const char *)item_value;
			} else if (g_str_equal(key, "Name") == TRUE) {
				name = (const char *)item_value;
			} else if (g_str_equal(key, "Host") == TRUE) {
				host = (const char *)item_value;
			} else if (g_str_equal(key, "VPN.Domain") == TRUE) {
				domain = (const char *)item_value;
			}

			DBG("%s %s", key, (char *)item_value);

			if (item_value != NULL)
				connman_dbus_dict_append_basic(&new_dict, key,
						value_type, &item_value);
			break;
		case DBUS_TYPE_ARRAY:
			if (g_str_equal(key, "Networks") == TRUE) {
				networks = get_user_networks(&value);
				connman_dbus_dict_append_array(&new_dict,
							"UserRoutes",
							DBUS_TYPE_DICT_ENTRY,
							append_routes,
							networks);
			}
			break;
		}

		dbus_message_iter_next(&array);
	}

	connman_dbus_dict_close(&new_iter, &new_dict);

	DBG("VPN type %s name %s host %s domain %s networks %p",
		type, name, host, domain, networks);

	if (host == NULL || domain == NULL) {
		err = -EINVAL;
		goto done;
	}

	if (type == NULL || name == NULL) {
		err = -EOPNOTSUPP;
		goto done;
	}

	ident = g_strdup_printf("%s_%s", host, domain);
	set_dbus_ident(ident);

	DBG("ident %s", ident);

	data = g_hash_table_lookup(vpn_connections, ident);
	if (data != NULL) {
		if (data->call != NULL || data->cb_data != NULL) {
			DBG("create configuration call already pending");
			err = -EINPROGRESS;
			goto done;
		}
	} else {
		char *path = g_strdup_printf("%s/connection/%s", VPN_PATH,
								ident);
		data = create_connection_data(path);
		g_free(path);

		if (data == NULL) {
			err = -ENOMEM;
			goto done;
		}

		g_hash_table_insert(vpn_connections, g_strdup(ident), data);
	}

	/*
	 * User called net.connman.Manager.ConnectProvider if we are here.
	 * So use the data from original message in the new msg.
	 */
	me = g_strdup(dbus_message_get_destination(msg));

	dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
	dbus_message_set_path(new_msg, "/");
	dbus_message_set_destination(new_msg, VPN_SERVICE);
	dbus_message_set_sender(new_msg, me);
	dbus_message_set_member(new_msg, "Create");

	user_data = g_try_new0(struct config_create_data, 1);
	if (user_data == NULL) {
		err = -ENOMEM;
		goto done;
	}

	user_data->callback = callback;
	user_data->message = dbus_message_ref(msg);
	user_data->path = NULL;

	DBG("cb %p msg %p", user_data, msg);

	result = dbus_connection_send_with_reply(connection, new_msg,
						&call, DBUS_TIMEOUT);
	if (result == FALSE || call == NULL) {
		err = -EIO;
		goto done;
	}

	dbus_pending_call_set_notify(call, configuration_create_reply,
							user_data, NULL);
	data->call = call;

done:
	if (new_msg != NULL)
		dbus_message_unref(new_msg);

	if (networks != NULL)
		g_slist_free_full(networks, destroy_route);

	g_free(me);
	return err;
}