Deleted Added
full compact
6,13c6,7
< * This program is free software; you can redistribute it and/or modify
< * it under the terms of the GNU General Public License version 2 as
< * published by the Free Software Foundation.
< *
< * Alternatively, this software may be distributed under the terms of BSD
< * license.
< *
< * See README and COPYING for more details.
---
> * This software may be distributed under the terms of the BSD license.
> * See README for more details.
23a18
> #include "dbus_dict_helpers.h"
26,35c21,24
< /**
< * recursive_iter_copy - Reads arguments from one iterator and
< * writes to another recursively
< * @from: iterator to read from
< * @to: iterator to write to
< *
< * Copies one iterator's elements to another. If any element in
< * iterator is of container type, its content is copied recursively
< */
< static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
---
> static dbus_bool_t fill_dict_with_properties(
> DBusMessageIter *dict_iter,
> const struct wpa_dbus_property_desc *props,
> const char *interface, void *user_data, DBusError *error)
37,94c26
<
< char *subtype = NULL;
< int type;
<
< /* iterate over iterator to copy */
< while ((type = dbus_message_iter_get_arg_type(from)) !=
< DBUS_TYPE_INVALID) {
<
< /* simply copy basic type entries */
< if (dbus_type_is_basic(type)) {
< if (dbus_type_is_fixed(type)) {
< /*
< * According to DBus documentation all
< * fixed-length types are guaranteed to fit
< * 8 bytes
< */
< dbus_uint64_t v;
< dbus_message_iter_get_basic(from, &v);
< dbus_message_iter_append_basic(to, type, &v);
< } else {
< char *v;
< dbus_message_iter_get_basic(from, &v);
< dbus_message_iter_append_basic(to, type, &v);
< }
< } else {
< /* recursively copy container type entries */
< DBusMessageIter write_subiter, read_subiter;
<
< dbus_message_iter_recurse(from, &read_subiter);
<
< if (type == DBUS_TYPE_VARIANT ||
< type == DBUS_TYPE_ARRAY) {
< subtype = dbus_message_iter_get_signature(
< &read_subiter);
< }
<
< dbus_message_iter_open_container(to, type, subtype,
< &write_subiter);
<
< recursive_iter_copy(&read_subiter, &write_subiter);
<
< dbus_message_iter_close_container(to, &write_subiter);
< if (subtype)
< dbus_free(subtype);
< }
<
< dbus_message_iter_next(from);
< }
< }
<
<
< static unsigned int fill_dict_with_properties(
< DBusMessageIter *dict_iter, const struct wpa_dbus_property_desc *props,
< const char *interface, const void *user_data)
< {
< DBusMessage *reply;
< DBusMessageIter entry_iter, ret_iter;
< unsigned int counter = 0;
---
> DBusMessageIter entry_iter;
98,103c30,33
< if (!os_strncmp(dsc->dbus_interface, interface,
< WPAS_DBUS_INTERFACE_MAX) &&
< dsc->access != W && dsc->getter) {
< reply = dsc->getter(NULL, user_data);
< if (!reply)
< continue;
---
> /* Only return properties for the requested D-Bus interface */
> if (os_strncmp(dsc->dbus_interface, interface,
> WPAS_DBUS_INTERFACE_MAX) != 0)
> continue;
105,109c35,37
< if (dbus_message_get_type(reply) ==
< DBUS_MESSAGE_TYPE_ERROR) {
< dbus_message_unref(reply);
< continue;
< }
---
> /* Skip write-only properties */
> if (dsc->getter == NULL)
> continue;
111c39,52
< dbus_message_iter_init(reply, &ret_iter);
---
> if (!dbus_message_iter_open_container(dict_iter,
> DBUS_TYPE_DICT_ENTRY,
> NULL, &entry_iter)) {
> dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
> "no memory");
> return FALSE;
> }
> if (!dbus_message_iter_append_basic(&entry_iter,
> DBUS_TYPE_STRING,
> &dsc->dbus_property)) {
> dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
> "no memory");
> return FALSE;
> }
113,118c54,56
< dbus_message_iter_open_container(dict_iter,
< DBUS_TYPE_DICT_ENTRY,
< NULL, &entry_iter);
< dbus_message_iter_append_basic(
< &entry_iter, DBUS_TYPE_STRING,
< &dsc->dbus_property);
---
> /* An error getting a property fails the request entirely */
> if (!dsc->getter(&entry_iter, error, user_data))
> return FALSE;
120,126c58
< recursive_iter_copy(&ret_iter, &entry_iter);
<
< dbus_message_iter_close_container(dict_iter,
< &entry_iter);
< dbus_message_unref(reply);
< counter++;
< }
---
> dbus_message_iter_close_container(dict_iter, &entry_iter);
129c61
< return counter;
---
> return TRUE;
145,147c77,78
< static DBusMessage * get_all_properties(
< DBusMessage *message, char *interface,
< struct wpa_dbus_object_desc *obj_dsc)
---
> static DBusMessage * get_all_properties(DBusMessage *message, char *interface,
> struct wpa_dbus_object_desc *obj_dsc)
149,150c80
< /* Create and initialize the return message */
< DBusMessage *reply = dbus_message_new_method_return(message);
---
> DBusMessage *reply;
152c82
< int props_num;
---
> DBusError error;
153a84,90
> reply = dbus_message_new_method_return(message);
> if (reply == NULL) {
> wpa_printf(MSG_ERROR, "%s: out of memory creating dbus reply",
> __func__);
> return NULL;
> }
>
154a92,99
> if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
> wpa_printf(MSG_ERROR, "%s: out of memory creating reply",
> __func__);
> dbus_message_unref(reply);
> reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
> "out of memory");
> return reply;
> }
156,168c101,104
< dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
< DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
< DBUS_TYPE_STRING_AS_STRING
< DBUS_TYPE_VARIANT_AS_STRING
< DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
< &dict_iter);
<
< props_num = fill_dict_with_properties(&dict_iter, obj_dsc->properties,
< interface, obj_dsc->user_data);
<
< dbus_message_iter_close_container(&iter, &dict_iter);
<
< if (props_num == 0) {
---
> dbus_error_init(&error);
> if (!fill_dict_with_properties(&dict_iter, obj_dsc->properties,
> interface, obj_dsc->user_data, &error))
> {
170,173c106,111
< reply = dbus_message_new_error(message,
< DBUS_ERROR_INVALID_ARGS,
< "No readable properties in "
< "this interface");
---
> reply = wpas_dbus_reply_new_from_error(message, &error,
> DBUS_ERROR_INVALID_ARGS,
> "No readable properties"
> " in this interface");
> dbus_error_free(&error);
> return reply;
175a114
> wpa_dbus_dict_close_write(&iter, &dict_iter);
222c161,165
< if (os_strcmp(dbus_message_get_signature(message), "ss"))
---
> DBusMessage *reply;
> DBusMessageIter iter;
> DBusError error;
>
> if (os_strcmp(dbus_message_get_signature(message), "ss")) {
224a168
> }
226,227c170,173
< if (dsc->access != W && dsc->getter)
< return dsc->getter(message, user_data);
---
> if (dsc->getter == NULL) {
> return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
> "Property is write-only");
> }
229,230c175,187
< return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
< "Property is write-only");
---
> reply = dbus_message_new_method_return(message);
> dbus_message_iter_init_append(reply, &iter);
>
> dbus_error_init(&error);
> if (dsc->getter(&iter, &error, user_data) == FALSE) {
> dbus_message_unref(reply);
> reply = wpas_dbus_reply_new_from_error(
> message, &error, DBUS_ERROR_FAILED,
> "Failed to read property");
> dbus_error_free(&error);
> }
>
> return reply;
238c195,199
< if (os_strcmp(dbus_message_get_signature(message), "ssv"))
---
> DBusMessage *reply;
> DBusMessageIter iter;
> DBusError error;
>
> if (os_strcmp(dbus_message_get_signature(message), "ssv")) {
240a202
> }
242,243c204,207
< if (dsc->access != R && dsc->setter)
< return dsc->setter(message, user_data);
---
> if (dsc->setter == NULL) {
> return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
> "Property is read-only");
> }
245,246c209,226
< return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
< "Property is read-only");
---
> dbus_message_iter_init(message, &iter);
> /* Skip the interface name and the property name */
> dbus_message_iter_next(&iter);
> dbus_message_iter_next(&iter);
>
> /* Iter will now point to the property's new value */
> dbus_error_init(&error);
> if (dsc->setter(&iter, &error, user_data) == TRUE) {
> /* Success */
> reply = dbus_message_new_method_return(message);
> } else {
> reply = wpas_dbus_reply_new_from_error(
> message, &error, DBUS_ERROR_FAILED,
> "Failed to set property");
> dbus_error_free(&error);
> }
>
> return reply;
554a535
> DBusError error;
568a550
> dbus_error_init(&error);
570,573c552,563
< if (!dbus_connection_register_object_path(con, path, &vtable,
< obj_desc)) {
< wpa_printf(MSG_ERROR, "dbus: Could not set up message "
< "handler for interface %s object %s", ifname, path);
---
> if (!dbus_connection_try_register_object_path(con, path, &vtable,
> obj_desc, &error)) {
> if (!os_strcmp(error.name, DBUS_ERROR_OBJECT_PATH_IN_USE)) {
> wpa_printf(MSG_DEBUG, "dbus: %s", error.message);
> } else {
> wpa_printf(MSG_ERROR, "dbus: Could not set up message "
> "handler for interface %s object %s",
> ifname, path);
> wpa_printf(MSG_ERROR, "dbus error: %s", error.name);
> wpa_printf(MSG_ERROR, "dbus: %s", error.message);
> }
> dbus_error_free(&error);
576a567
> dbus_error_free(&error);
614,616c605,607
< static void put_changed_properties(const struct wpa_dbus_object_desc *obj_dsc,
< const char *interface,
< DBusMessageIter *dict_iter)
---
> static dbus_bool_t put_changed_properties(
> const struct wpa_dbus_object_desc *obj_dsc, const char *interface,
> DBusMessageIter *dict_iter, int clear_changed)
618,619c609
< DBusMessage *getter_reply;
< DBusMessageIter prop_iter, entry_iter;
---
> DBusMessageIter entry_iter;
621a612
> DBusError error;
630c621,622
< obj_dsc->prop_changed_flags[i] = 0;
---
> if (clear_changed)
> obj_dsc->prop_changed_flags[i] = 0;
632,643c624
< getter_reply = dsc->getter(NULL, obj_dsc->user_data);
< if (!getter_reply ||
< dbus_message_get_type(getter_reply) ==
< DBUS_MESSAGE_TYPE_ERROR) {
< wpa_printf(MSG_ERROR, "dbus: %s: Cannot get new value "
< "of property %s", __func__,
< dsc->dbus_property);
< continue;
< }
<
< if (!dbus_message_iter_init(getter_reply, &prop_iter) ||
< !dbus_message_iter_open_container(dict_iter,
---
> if (!dbus_message_iter_open_container(dict_iter,
645,646c626,629
< NULL, &entry_iter) ||
< !dbus_message_iter_append_basic(&entry_iter,
---
> NULL, &entry_iter))
> return FALSE;
>
> if (!dbus_message_iter_append_basic(&entry_iter,
649c632
< goto err;
---
> return FALSE;
651c634,648
< recursive_iter_copy(&prop_iter, &entry_iter);
---
> dbus_error_init(&error);
> if (!dsc->getter(&entry_iter, &error, obj_dsc->user_data)) {
> if (dbus_error_is_set (&error)) {
> wpa_printf(MSG_ERROR, "dbus: %s: Cannot get "
> "new value of property %s: (%s) %s",
> __func__, dsc->dbus_property,
> error.name, error.message);
> } else {
> wpa_printf(MSG_ERROR, "dbus: %s: Cannot get "
> "new value of property %s",
> __func__, dsc->dbus_property);
> }
> dbus_error_free(&error);
> return FALSE;
> }
654,656c651
< goto err;
<
< dbus_message_unref(getter_reply);
---
> return FALSE;
658a654,698
> return TRUE;
> }
>
>
> static void do_send_prop_changed_signal(
> DBusConnection *con, const char *path, const char *interface,
> const struct wpa_dbus_object_desc *obj_dsc)
> {
> DBusMessage *msg;
> DBusMessageIter signal_iter, dict_iter;
>
> msg = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
> "PropertiesChanged");
> if (msg == NULL)
> return;
>
> dbus_message_iter_init_append(msg, &signal_iter);
>
> if (!dbus_message_iter_append_basic(&signal_iter, DBUS_TYPE_STRING,
> &interface))
> goto err;
>
> /* Changed properties dict */
> if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
> "{sv}", &dict_iter))
> goto err;
>
> if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0))
> goto err;
>
> if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
> goto err;
>
> /* Invalidated properties array (empty) */
> if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
> "s", &dict_iter))
> goto err;
>
> if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
> goto err;
>
> dbus_connection_send(con, msg, NULL);
>
> out:
> dbus_message_unref(msg);
662c702,704
< wpa_printf(MSG_ERROR, "dbus: %s: Cannot construct signal", __func__);
---
> wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
> __func__);
> goto out;
666c708
< static void send_prop_changed_signal(
---
> static void do_send_deprecated_prop_changed_signal(
683c725,726
< put_changed_properties(obj_dsc, interface, &dict_iter);
---
> if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1))
> goto err;
700a744,766
> static void send_prop_changed_signal(
> DBusConnection *con, const char *path, const char *interface,
> const struct wpa_dbus_object_desc *obj_dsc)
> {
> /*
> * First, send property change notification on the standardized
> * org.freedesktop.DBus.Properties interface. This call will not
> * clear the property change bits, so that they are preserved for
> * the call that follows.
> */
> do_send_prop_changed_signal(con, path, interface, obj_dsc);
>
> /*
> * Now send PropertiesChanged on our own interface for backwards
> * compatibility. This is deprecated and will be removed in a future
> * release.
> */
> do_send_deprecated_prop_changed_signal(con, path, interface, obj_dsc);
>
> /* Property change bits have now been cleared. */
> }
>
>
852c918
< * @dict_iter: correct, open DBus dictionary iterator.
---
> * @iter: DBus message iter at which to append property dictionary.
859,861c925,928
< void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
< const char *path, const char *interface,
< DBusMessageIter *dict_iter)
---
> dbus_bool_t wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
> const char *path,
> const char *interface,
> DBusMessageIter *iter)
863a931,932
> DBusMessageIter dict_iter;
> DBusError error;
868,870c937,939
< wpa_printf(MSG_ERROR, "dbus: wpa_dbus_get_object_properties: "
< "could not obtain object's private data: %s", path);
< return;
---
> wpa_printf(MSG_ERROR, "dbus: %s: could not obtain object's "
> "private data: %s", __func__, path);
> return FALSE;
873,874c942,960
< fill_dict_with_properties(dict_iter, obj_desc->properties,
< interface, obj_desc->user_data);
---
> if (!wpa_dbus_dict_open_write(iter, &dict_iter)) {
> wpa_printf(MSG_ERROR, "dbus: %s: failed to open message dict",
> __func__);
> return FALSE;
> }
>
> dbus_error_init(&error);
> if (!fill_dict_with_properties(&dict_iter, obj_desc->properties,
> interface, obj_desc->user_data,
> &error)) {
> wpa_printf(MSG_ERROR, "dbus: %s: failed to get object"
> " properties: (%s) %s", __func__,
> dbus_error_is_set(&error) ? error.name : "none",
> dbus_error_is_set(&error) ? error.message : "none");
> dbus_error_free(&error);
> return FALSE;
> }
>
> return wpa_dbus_dict_close_write(iter, &dict_iter);
875a962,1061
>
> /**
> * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
> * @path: The dbus object path
> * @p2p_persistent_group: indicates whether to parse the path as a P2P
> * persistent group object
> * @network: (out) the configured network this object path refers to, if any
> * @bssid: (out) the scanned bssid this object path refers to, if any
> * Returns: The object path of the network interface this path refers to
> *
> * For a given object path, decomposes the object path into object id, network,
> * and BSSID parts, if those parts exist.
> */
> char *wpas_dbus_new_decompose_object_path(const char *path,
> int p2p_persistent_group,
> char **network,
> char **bssid)
> {
> const unsigned int dev_path_prefix_len =
> os_strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
> char *obj_path_only;
> char *next_sep;
>
> /* Be a bit paranoid about path */
> if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
> dev_path_prefix_len))
> return NULL;
>
> /* Ensure there's something at the end of the path */
> if ((path + dev_path_prefix_len)[0] == '\0')
> return NULL;
>
> obj_path_only = os_strdup(path);
> if (obj_path_only == NULL)
> return NULL;
>
> next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
> if (next_sep != NULL) {
> const char *net_part = os_strstr(
> next_sep, p2p_persistent_group ?
> WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/" :
> WPAS_DBUS_NEW_NETWORKS_PART "/");
> const char *bssid_part = os_strstr(
> next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
>
> if (network && net_part) {
> /* Deal with a request for a configured network */
> const char *net_name = net_part +
> os_strlen(p2p_persistent_group ?
> WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART
> "/" :
> WPAS_DBUS_NEW_NETWORKS_PART "/");
> *network = NULL;
> if (os_strlen(net_name))
> *network = os_strdup(net_name);
> } else if (bssid && bssid_part) {
> /* Deal with a request for a scanned BSSID */
> const char *bssid_name = bssid_part +
> os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
> if (os_strlen(bssid_name))
> *bssid = os_strdup(bssid_name);
> else
> *bssid = NULL;
> }
>
> /* Cut off interface object path before "/" */
> *next_sep = '\0';
> }
>
> return obj_path_only;
> }
>
>
> /**
> * wpas_dbus_reply_new_from_error - Create a new D-Bus error message from a
> * dbus error structure
> * @message: The original request message for which the error is a reply
> * @error: The error containing a name and a descriptive error cause
> * @fallback_name: A generic error name if @error was not set
> * @fallback_string: A generic error string if @error was not set
> * Returns: A new D-Bus error message
> *
> * Given a DBusMessage structure, creates a new D-Bus error message using
> * the error name and string contained in that structure.
> */
> DBusMessage * wpas_dbus_reply_new_from_error(DBusMessage *message,
> DBusError *error,
> const char *fallback_name,
> const char *fallback_string)
> {
> if (error && error->name && error->message) {
> return dbus_message_new_error(message, error->name,
> error->message);
> }
> if (fallback_name && fallback_string) {
> return dbus_message_new_error(message, fallback_name,
> fallback_string);
> }
> return NULL;
> }