diff --git a/0001-dbus-clean-up-new-D-Bus-interface-getters-setters.patch b/0001-dbus-clean-up-new-D-Bus-interface-getters-setters.patch new file mode 100644 index 0000000..e06b5db --- /dev/null +++ b/0001-dbus-clean-up-new-D-Bus-interface-getters-setters.patch @@ -0,0 +1,3311 @@ +From 822596cfa5e37cdad710b9e282c2bcc267c3fe01 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Tue, 26 Jul 2011 19:48:01 -0500 +Subject: [PATCH] dbus: clean up new D-Bus interface getters/setters + +A number of fixes/improvements here: + +1) Remove casting of getter/setter function types which allows +us to change the prototypes in the future and not have hard-to-find +runtime segfaults + +2) Instead of having the getters create a fake reply message which +then gets its arguments copied into the real reply message, and is +then disposed, just pass message iters around and have them add +their arguments to the message itself + +3) For setters, just pass in the message iter positioned at the +start of the argument list, instead of each setter having to skip +over the standard interface+property name + +4) Convert error handling to use DBusError and return the error +back down through the call stacks to the function that will +actually send the error back to the caller, instead of having a +fake DBusMessage of type DBUS_MESSAGE_TYPE_ERROR that then +needs to have the error extracted from it. + +But most of all, this fixes various segfaults (like rh #725517 +and #678625) which were caused by some functions deep down in the +getter callpaths wanting a source DBusMessage* when the getters were +used for two things: signals (which don't have a source DBusMessage) +and methods (which will have a source DBusMessage that's being +replied to). This duality made the code fragile when handling +errors like invalid IEs over the air. +--- + wpa_supplicant/dbus/dbus_dict_helpers.c | 14 +- + wpa_supplicant/dbus/dbus_dict_helpers.h | 3 +- + wpa_supplicant/dbus/dbus_new.c | 127 ++-- + wpa_supplicant/dbus/dbus_new_handlers.c | 1236 +++++++++++++-------------- + wpa_supplicant/dbus/dbus_new_handlers.h | 204 +++-- + wpa_supplicant/dbus/dbus_new_handlers_wps.c | 32 +- + wpa_supplicant/dbus/dbus_new_helpers.c | 365 +++++---- + wpa_supplicant/dbus/dbus_new_helpers.h | 17 +- + wpa_supplicant/dbus/dbus_old_handlers.c | 8 +- + 9 files changed, 1009 insertions(+), 997 deletions(-) + +diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.c b/wpa_supplicant/dbus/dbus_dict_helpers.c +index b3aff40..dbfdcc1 100644 +--- a/wpa_supplicant/dbus/dbus_dict_helpers.c ++++ b/wpa_supplicant/dbus/dbus_dict_helpers.c +@@ -593,18 +593,26 @@ dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, + * @param iter A valid DBusMessageIter pointing to the start of the dict + * @param iter_dict (out) A DBusMessageIter to be passed to + * wpa_dbus_dict_read_next_entry() ++ * @error on failure a descriptive error + * @return TRUE on success, FALSE on failure + * + */ + dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter, +- DBusMessageIter *iter_dict) ++ DBusMessageIter *iter_dict, ++ DBusError *error) + { +- if (!iter || !iter_dict) ++ if (!iter || !iter_dict) { ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, ++ "[internal] missing message iterators"); + return FALSE; ++ } + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY || +- dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) ++ dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) { ++ dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, ++ "unexpected message argument types"); + return FALSE; ++ } + + dbus_message_iter_recurse(iter, iter_dict); + return TRUE; +diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.h b/wpa_supplicant/dbus/dbus_dict_helpers.h +index eb31575..9d23efa 100644 +--- a/wpa_supplicant/dbus/dbus_dict_helpers.h ++++ b/wpa_supplicant/dbus/dbus_dict_helpers.h +@@ -125,7 +125,8 @@ struct wpa_dbus_dict_entry { + }; + + dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter, +- DBusMessageIter *iter_dict); ++ DBusMessageIter *iter_dict, ++ DBusError *error); + + dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, + struct wpa_dbus_dict_entry *entry); +diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c +index c66640a..2da9fef 100644 +--- a/wpa_supplicant/dbus/dbus_new.c ++++ b/wpa_supplicant/dbus/dbus_new.c +@@ -42,7 +42,7 @@ static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s, + { + struct wpas_dbus_priv *iface; + DBusMessage *msg; +- DBusMessageIter iter, iter_dict; ++ DBusMessageIter iter; + + iface = wpa_s->global->dbus; + +@@ -61,14 +61,9 @@ static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s, + goto err; + + if (properties) { +- if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) +- goto err; +- +- wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path, +- WPAS_DBUS_NEW_IFACE_INTERFACE, +- &iter_dict); +- +- if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) ++ if (!wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path, ++ WPAS_DBUS_NEW_IFACE_INTERFACE, ++ &iter)) + goto err; + } + +@@ -157,7 +152,7 @@ static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s, + { + struct wpas_dbus_priv *iface; + DBusMessage *msg; +- DBusMessageIter iter, iter_dict; ++ DBusMessageIter iter; + + iface = wpa_s->global->dbus; + +@@ -177,14 +172,9 @@ static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s, + goto err; + + if (properties) { +- if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) +- goto err; +- +- wpa_dbus_get_object_properties(iface, bss_obj_path, +- WPAS_DBUS_NEW_IFACE_BSS, +- &iter_dict); +- +- if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) ++ if (!wpa_dbus_get_object_properties(iface, bss_obj_path, ++ WPAS_DBUS_NEW_IFACE_BSS, ++ &iter)) + goto err; + } + +@@ -304,7 +294,7 @@ static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s, + { + struct wpas_dbus_priv *iface; + DBusMessage *msg; +- DBusMessageIter iter, iter_dict; ++ DBusMessageIter iter; + char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; + + iface = wpa_s->global->dbus; +@@ -330,14 +320,9 @@ static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s, + goto err; + + if (properties) { +- if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) +- goto err; +- +- wpa_dbus_get_object_properties(iface, net_obj_path, +- WPAS_DBUS_NEW_IFACE_NETWORK, +- &iter_dict); +- +- if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) ++ if (!wpa_dbus_get_object_properties(iface, net_obj_path, ++ WPAS_DBUS_NEW_IFACE_NETWORK, ++ &iter)) + goto err; + } + +@@ -655,30 +655,27 @@ void wpas_dbus_signal_prop_changed(struc + + switch (property) { + case WPAS_DBUS_PROP_AP_SCAN: +- getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan; ++ getter = wpas_dbus_getter_ap_scan; + prop = "ApScan"; + break; + case WPAS_DBUS_PROP_SCANNING: +- getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning; ++ getter = wpas_dbus_getter_scanning; + prop = "Scanning"; + break; + case WPAS_DBUS_PROP_STATE: +- getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state; ++ getter = wpas_dbus_getter_state; + prop = "State"; + break; + case WPAS_DBUS_PROP_CURRENT_BSS: +- getter = (WPADBusPropertyAccessor) +- wpas_dbus_getter_current_bss; ++ getter = wpas_dbus_getter_current_bss; + prop = "CurrentBSS"; + break; + case WPAS_DBUS_PROP_CURRENT_NETWORK: +- getter = (WPADBusPropertyAccessor) +- wpas_dbus_getter_current_network; ++ getter = wpas_dbus_getter_current_network; + prop = "CurrentNetwork"; + break; + case WPAS_DBUS_PROP_BSSS: +- getter = (WPADBusPropertyAccessor) +- wpas_dbus_getter_bsss; ++ getter = wpas_dbus_getter_bsss; + prop = "BSSs"; + break; + default: +@@ -859,27 +842,27 @@ static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { + + static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { + { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level, +- (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level, ++ wpas_dbus_getter_debug_level, ++ wpas_dbus_setter_debug_level, + RW + }, + { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp, +- (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp, ++ wpas_dbus_getter_debug_timestamp, ++ wpas_dbus_setter_debug_timestamp, + RW + }, + { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys, +- (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys, ++ wpas_dbus_getter_debug_show_keys, ++ wpas_dbus_setter_debug_show_keys, + RW + }, + { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", +- (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces, ++ wpas_dbus_getter_interfaces, + NULL, + R + }, + { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", +- (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods, ++ wpas_dbus_getter_eap_methods, + NULL, + R + }, +@@ -976,13 +959,13 @@ static void wpa_dbus_free(void *ptr) + + static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { + { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", +- (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties, +- (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties, ++ wpas_dbus_getter_network_properties, ++ wpas_dbus_setter_network_properties, + RW + }, + { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_enabled, +- (WPADBusPropertyAccessor) wpas_dbus_setter_enabled, ++ wpas_dbus_getter_enabled, ++ wpas_dbus_setter_enabled, + RW + }, + { NULL, NULL, NULL, NULL, NULL, 0 } +@@ -1104,52 +1087,52 @@ int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) + + static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { + { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid, ++ wpas_dbus_getter_bss_ssid, + NULL, + R + }, + { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid, ++ wpas_dbus_getter_bss_bssid, + NULL, + R + }, + { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy, ++ wpas_dbus_getter_bss_privacy, + NULL, + R + }, + { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode, ++ wpas_dbus_getter_bss_mode, + NULL, + R + }, + { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal, ++ wpas_dbus_getter_bss_signal, + NULL, + R + }, + { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency, ++ wpas_dbus_getter_bss_frequency, + NULL, + R + }, + { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates, ++ wpas_dbus_getter_bss_rates, + NULL, + R + }, + { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa, ++ wpas_dbus_getter_bss_wpa, + NULL, + R + }, + { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn, ++ wpas_dbus_getter_bss_rsn, + NULL, + R + }, + { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies, ++ wpas_dbus_getter_bss_ies, + NULL, + R + }, +@@ -1352,58 +1335,58 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { + + static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { + { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", +- (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities, ++ wpas_dbus_getter_capabilities, + NULL, R + }, + { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_state, ++ wpas_dbus_getter_state, + NULL, R + }, + { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_scanning, ++ wpas_dbus_getter_scanning, + NULL, R + }, + { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", +- (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan, +- (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan, ++ wpas_dbus_getter_ap_scan, ++ wpas_dbus_setter_ap_scan, + RW + }, + { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_ifname, ++ wpas_dbus_getter_ifname, + NULL, R + }, + { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_driver, ++ wpas_dbus_getter_driver, + NULL, R + }, + { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname, ++ wpas_dbus_getter_bridge_ifname, + NULL, R + }, + { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", +- (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss, ++ wpas_dbus_getter_current_bss, + NULL, R + }, + { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", +- (WPADBusPropertyAccessor) wpas_dbus_getter_current_network, ++ wpas_dbus_getter_current_network, + NULL, R + }, + { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", +- (WPADBusPropertyAccessor) wpas_dbus_getter_blobs, ++ wpas_dbus_getter_blobs, + NULL, R + }, + { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", +- (WPADBusPropertyAccessor) wpas_dbus_getter_bsss, ++ wpas_dbus_getter_bsss, + NULL, R + }, + { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", +- (WPADBusPropertyAccessor) wpas_dbus_getter_networks, ++ wpas_dbus_getter_networks, + NULL, R + }, + #ifdef CONFIG_WPS + { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", +- (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials, +- (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials, ++ wpas_dbus_getter_process_credentials, ++ wpas_dbus_setter_process_credentials, + RW + }, + #endif /* CONFIG_WPS */ +diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c +index e2b5e50..af17a16 100644 +--- a/wpa_supplicant/dbus/dbus_new_handlers.c ++++ b/wpa_supplicant/dbus/dbus_new_handlers.c +@@ -213,36 +213,35 @@ static struct wpa_supplicant * get_iface_by_dbus_path( + + /** + * set_network_properties - Set properties of a configured network +- * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * @ssid: wpa_ssid structure for a configured network + * @iter: DBus message iterator containing dictionary of network + * properties to set. +- * Returns: NULL when succeed or DBus error on failure ++ * @error: On failure, an error describing the failure ++ * Returns: TRUE if the request succeeds, FALSE if it failed + * + * Sets network configuration with parameters given id DBus dictionary + */ +-static DBusMessage * set_network_properties(DBusMessage *message, +- struct wpa_supplicant *wpa_s, +- struct wpa_ssid *ssid, +- DBusMessageIter *iter) ++dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, ++ struct wpa_ssid *ssid, ++ DBusMessageIter *iter, ++ DBusError *error) + { +- + struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; +- DBusMessage *reply = NULL; + DBusMessageIter iter_dict; ++ char *value = NULL; + +- if (!wpa_dbus_dict_open_read(iter, &iter_dict)) +- return wpas_dbus_error_invalid_args(message, NULL); ++ if (!wpa_dbus_dict_open_read(iter, &iter_dict, error)) ++ return FALSE; + + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { +- char *value = NULL; + size_t size = 50; + int ret; +- if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { +- reply = wpas_dbus_error_invalid_args(message, NULL); +- break; +- } ++ ++ if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) ++ goto error; ++ ++ value = NULL; + if (entry.type == DBUS_TYPE_ARRAY && + entry.array_type == DBUS_TYPE_BYTE) { + if (entry.array_len <= 0) +@@ -311,71 +310,59 @@ static DBusMessage * set_network_properties(DBusMessage *message, + + os_free(value); + wpa_dbus_dict_entry_clear(&entry); +- continue; +- +- error: +- os_free(value); +- reply = wpas_dbus_error_invalid_args(message, entry.key); +- wpa_dbus_dict_entry_clear(&entry); +- break; + } + +- return reply; ++ return TRUE; ++ ++error: ++ os_free(value); ++ wpa_dbus_dict_entry_clear(&entry); ++ dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, ++ "invalid message format"); ++ return FALSE; + } + + + /** + * wpas_dbus_simple_property_getter - Get basic type property +- * @message: Pointer to incoming dbus message ++ * @iter: Message iter to use when appending arguments + * @type: DBus type of property (must be basic type) + * @val: pointer to place holding property value +- * Returns: The DBus message containing response for Properties.Get call +- * or DBus error message if error occurred. ++ * @error: On failure an error describing the failure ++ * Returns: TRUE if the request was successful, FALSE if it failed + * + * Generic getter for basic type properties. Type is required to be basic. + */ +-DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message, +- const int type, const void *val) ++dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter, ++ const int type, ++ const void *val, ++ DBusError *error) + { +- DBusMessage *reply = NULL; +- DBusMessageIter iter, variant_iter; ++ DBusMessageIter variant_iter; + + if (!dbus_type_is_basic(type)) { +- wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:" +- " given type is not basic"); +- return wpas_dbus_error_unknown_error(message, NULL); ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: given type is not basic", __func__); ++ return FALSE; + } + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- +- if (reply != NULL) { +- dbus_message_iter_init_append(reply, &iter); +- if (!dbus_message_iter_open_container( +- &iter, DBUS_TYPE_VARIANT, +- wpa_dbus_type_as_string(type), &variant_iter) || +- !dbus_message_iter_append_basic(&variant_iter, type, +- val) || +- !dbus_message_iter_close_container(&iter, &variant_iter)) { +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_property_getter: out of " +- "memory to put property value into " +- "message"); +- dbus_message_unref(reply); +- reply = dbus_message_new_error(message, +- DBUS_ERROR_NO_MEMORY, +- NULL); +- } +- } else { +- wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:" +- " out of memory to return property value"); +- reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); +- } ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, ++ wpa_dbus_type_as_string(type), ++ &variant_iter)) ++ goto error; + +- return reply; ++ if (!dbus_message_iter_append_basic(&variant_iter, type, val)) ++ goto error; ++ ++ if (!dbus_message_iter_close_container(iter, &variant_iter)) ++ goto error; ++ ++ return TRUE; ++ ++error: ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: error constructing reply", __func__); ++ return FALSE; + } + + +@@ -388,98 +375,75 @@ DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message, + * + * Generic setter for basic type properties. Type is required to be basic. + */ +-DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message, +- const int type, void *val) ++dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter, ++ DBusError *error, ++ const int type, void *val) + { +- DBusMessageIter iter, variant_iter; ++ DBusMessageIter variant_iter; + + if (!dbus_type_is_basic(type)) { +- wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:" +- " given type is not basic"); +- return wpas_dbus_error_unknown_error(message, NULL); ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: given type is not basic", __func__); ++ return FALSE; + } + +- if (!dbus_message_iter_init(message, &iter)) { +- wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:" +- " out of memory to return scanning state"); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); +- } +- +- /* omit first and second argument and get value from third */ +- dbus_message_iter_next(&iter); +- dbus_message_iter_next(&iter); +- dbus_message_iter_recurse(&iter, &variant_iter); +- ++ /* Look at the new value */ ++ dbus_message_iter_recurse(iter, &variant_iter); + if (dbus_message_iter_get_arg_type(&variant_iter) != type) { +- wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:" +- " wrong property type"); +- return wpas_dbus_error_invalid_args(message, +- "wrong property type"); ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, ++ "wrong property type"); ++ return FALSE; + } + dbus_message_iter_get_basic(&variant_iter, val); + +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_simple_array_property_getter - Get array type property +- * @message: Pointer to incoming dbus message ++ * @iter: Pointer to incoming dbus message iterator + * @type: DBus type of property array elements (must be basic type) + * @array: pointer to array of elements to put into response message + * @array_len: length of above array +- * Returns: The DBus message containing response for Properties.Get call +- * or DBus error message if error occurred. ++ * @error: a pointer to an error to fill on failure ++ * Returns: TRUE if the request succeeded, FALSE if it failed + * + * Generic getter for array type properties. Array elements type is + * required to be basic. + */ +-DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message, +- const int type, +- const void *array, +- size_t array_len) ++dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter, ++ const int type, ++ const void *array, ++ size_t array_len, ++ DBusError *error) + { +- DBusMessage *reply = NULL; +- DBusMessageIter iter, variant_iter, array_iter; ++ DBusMessageIter variant_iter, array_iter; + char type_str[] = "a?"; /* ? will be replaced with subtype letter; */ + const char *sub_type_str; + size_t element_size, i; + + if (!dbus_type_is_basic(type)) { +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_array_property_getter: given " +- "type is not basic"); +- return wpas_dbus_error_unknown_error(message, NULL); ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: given type is not basic", __func__); ++ return FALSE; + } + + sub_type_str = wpa_dbus_type_as_string(type); + type_str[1] = sub_type_str[0]; + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- if (reply == NULL) { +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_array_property_getter: out of " +- "memory to create return message"); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, ++ type_str, &variant_iter)) { ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: failed to construct message 1", __func__); ++ return FALSE; + } + +- dbus_message_iter_init_append(reply, &iter); +- +- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, +- type_str, &variant_iter) || +- !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, ++ if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, + sub_type_str, &array_iter)) { +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_array_property_getter: out of " +- "memory to open container"); +- dbus_message_unref(reply); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: failed to construct message 2", __func__); ++ return FALSE; + } + + switch(type) { +@@ -507,11 +471,9 @@ DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message, + element_size = sizeof(char *); + break; + default: +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_array_property_getter: " +- "fatal: unknown element type"); +- element_size = 1; +- break; ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: unknown element type %d", __func__, type); ++ return FALSE; + } + + for (i = 0; i < array_len; i++) { +@@ -519,17 +481,19 @@ DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message, + array + i * element_size); + } + +- if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || +- !dbus_message_iter_close_container(&iter, &variant_iter)) { +- wpa_printf(MSG_ERROR, "dbus: " +- "wpas_dbus_simple_array_property_getter: out of " +- "memory to close container"); +- dbus_message_unref(reply); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) { ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: failed to construct message 3", __func__); ++ return FALSE; + } + +- return reply; ++ if (!dbus_message_iter_close_container(iter, &variant_iter)) { ++ dbus_set_error(error, DBUS_ERROR_FAILED, ++ "%s: failed to construct message 4", __func__); ++ return FALSE; ++ } ++ ++ return TRUE; + } + + +@@ -557,7 +521,7 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, + + dbus_message_iter_init(message, &iter); + +- if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) ++ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) + goto error; + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { + if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) +@@ -706,79 +670,85 @@ DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message, + + /** + * wpas_dbus_getter_debug_level - Get debug level +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: DBus message with value of debug level ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "DebugLevel" property. + */ +-DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { + const char *str; + int idx = wpa_debug_level; ++ + if (idx < 0) + idx = 0; + if (idx > 4) + idx = 4; + str = debug_strings[idx]; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &str); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &str, error); + } + + + /** + * wpas_dbus_getter_debug_timestamp - Get debug timestamp +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: DBus message with value of debug timestamp ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "DebugTimestamp" property. + */ +-DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &wpa_debug_timestamp); +- ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &wpa_debug_timestamp, error); + } + + + /** + * wpas_dbus_getter_debug_show_keys - Get debug show keys +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: DBus message with value of debug show_keys ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "DebugShowKeys" property. + */ +-DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &wpa_debug_show_keys); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &wpa_debug_show_keys, error); + + } + + /** + * wpas_dbus_setter_debug_level - Set debug level +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: %NULL or DBus error message ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "DebugLevel" property. + */ +-DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- DBusMessage *reply; ++ struct wpa_global *global = user_data; + const char *str = NULL; + int i, val = -1; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING, +- &str); +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, ++ &str)) ++ return FALSE; + + for (i = 0; debug_strings[i]; i++) + if (os_strcmp(debug_strings[i], str) == 0) { +@@ -789,138 +759,142 @@ DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message, + if (val < 0 || + wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp, + wpa_debug_show_keys)) { +- dbus_message_unref(reply); +- return wpas_dbus_error_invalid_args( +- message, "Wrong debug level value"); ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, "wrong debug " ++ "level value"); ++ return FALSE; + } + +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_setter_debug_timestamp - Set debug timestamp +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: %NULL or DBus error message ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "DebugTimestamp" property. + */ +-DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- DBusMessage *reply; ++ struct wpa_global *global = user_data; + dbus_bool_t val; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, +- &val); +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, ++ &val)) ++ return FALSE; + + wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0, + wpa_debug_show_keys); + +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_setter_debug_show_keys - Set debug show keys +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: %NULL or DBus error message ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "DebugShowKeys" property. + */ +-DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- DBusMessage *reply; ++ struct wpa_global *global = user_data; + dbus_bool_t val; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, +- &val); +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, ++ &val)) ++ return FALSE; + + wpa_supplicant_set_debug_params(global, wpa_debug_level, + wpa_debug_timestamp, + val ? 1 : 0); + +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_getter_interfaces - Request registered interfaces list +- * @message: Pointer to incoming dbus message +- * @global: %wpa_supplicant global data structure +- * Returns: The object paths array containing registered interfaces +- * objects paths or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Interfaces" property. Handles requests + * by dbus clients to return list of registered interfaces objects + * paths + */ +-DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message, +- struct wpa_global *global) ++dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_global *global = user_data; + struct wpa_supplicant *wpa_s; + const char **paths; + unsigned int i = 0, num = 0; ++ dbus_bool_t success; + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) + num++; + + paths = os_zalloc(num * sizeof(char*)); + if (!paths) { +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) + paths[i] = wpa_s->dbus_new_path; + +- reply = wpas_dbus_simple_array_property_getter(message, +- DBUS_TYPE_OBJECT_PATH, +- paths, num); ++ success = wpas_dbus_simple_array_property_getter(iter, ++ DBUS_TYPE_OBJECT_PATH, ++ paths, num, error); + + os_free(paths); +- return reply; ++ return success; + } + + + /** + * wpas_dbus_getter_eap_methods - Request supported EAP methods list +- * @message: Pointer to incoming dbus message +- * @nothing: not used argument. may be NULL or anything else +- * Returns: The object paths array containing supported EAP methods +- * represented by strings or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "EapMethods" property. Handles requests + * by dbus clients to return list of strings with supported EAP methods + */ +-DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing) ++dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- DBusMessage *reply = NULL; + char **eap_methods; + size_t num_items = 0; ++ dbus_bool_t success; + + eap_methods = eap_get_names_as_string_array(&num_items); + if (!eap_methods) { +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + +- reply = wpas_dbus_simple_array_property_getter(message, +- DBUS_TYPE_STRING, +- eap_methods, num_items); ++ success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_STRING, ++ eap_methods, num_items, ++ error); + + while (num_items) + os_free(eap_methods[--num_items]); + os_free(eap_methods); +- return reply; ++ return success; + } + + +@@ -1326,6 +1300,7 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, + DBusMessageIter iter; + struct wpa_ssid *ssid = NULL; + char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; ++ DBusError error; + + dbus_message_iter_init(message, &iter); + +@@ -1343,11 +1318,15 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, + ssid->disabled = 1; + wpa_config_set_network_defaults(ssid); + +- reply = set_network_properties(message, wpa_s, ssid, &iter); +- if (reply) { ++ dbus_error_init(&error); ++ if (!set_network_properties(wpa_s, ssid, &iter, &error)) { + wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:" + "control interface couldn't set network " + "properties"); ++ reply = wpas_dbus_reply_new_from_error(message, &error, ++ DBUS_ERROR_INVALID_ARGS, ++ "Failed to add network"); ++ dbus_error_free(&error); + goto err; + } + +@@ -1661,34 +1640,26 @@ DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, + + /** + * wpas_dbus_getter_capabilities - Return interface capabilities +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a dict of strings ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Capabilities" property of an interface. + */ +-DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + struct wpa_driver_capa capa; + int res; +- DBusMessageIter iter, iter_dict; +- DBusMessageIter iter_dict_entry, iter_dict_val, iter_array, ++ DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array, + variant_iter; + const char *scans[] = { "active", "passive", "ssid" }; + const char *modes[] = { "infrastructure", "ad-hoc", "ap" }; + int n = sizeof(modes) / sizeof(char *); + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- if (!reply) +- goto nomem; +- +- dbus_message_iter_init_append(reply, &iter); +- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + "a{sv}", &variant_iter)) + goto nomem; + +@@ -1956,34 +1927,33 @@ DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message, + + if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) + goto nomem; +- if (!dbus_message_iter_close_container(&iter, &variant_iter)) ++ if (!dbus_message_iter_close_container(iter, &variant_iter)) + goto nomem; + +- return reply; ++ return TRUE; + + nomem: +- if (reply) +- dbus_message_unref(reply); +- +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + + /** + * wpas_dbus_getter_state - Get interface state +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a STRING representing the current +- * interface state ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "State" property. + */ +-DBusMessage * wpas_dbus_getter_state(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + const char *str_state; + char *state_ls, *tmp; ++ dbus_bool_t success = FALSE; + + str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); + +@@ -1991,141 +1961,154 @@ DBusMessage * wpas_dbus_getter_state(DBusMessage *message, + */ + state_ls = tmp = os_strdup(str_state); + if (!tmp) { +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + while (*tmp) { + *tmp = tolower(*tmp); + tmp++; + } + +- reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &state_ls); ++ success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &state_ls, error); + + os_free(state_ls); + +- return reply; ++ return success; + } + + + /** + * wpas_dbus_new_iface_get_scanning - Get interface scanning state +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing whether the interface is scanning ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "scanning" property. + */ +-DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { ++ struct wpa_supplicant *wpa_s = user_data; + dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &scanning); ++ ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &scanning, error); + } + + + /** + * wpas_dbus_getter_ap_scan - Control roaming mode +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A message containong value of ap_scan variable ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter function for "ApScan" property. + */ +-DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { ++ struct wpa_supplicant *wpa_s = user_data; + dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32, +- &ap_scan); ++ ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, ++ &ap_scan, error); + } + + + /** + * wpas_dbus_setter_ap_scan - Control roaming mode +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: NULL ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter function for "ApScan" property. + */ +-DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + dbus_uint32_t ap_scan; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32, +- &ap_scan); +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, ++ &ap_scan)) ++ return FALSE; + + if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { +- return wpas_dbus_error_invalid_args( +- message, "ap_scan must equal 0, 1 or 2"); ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, ++ "ap_scan must be 0, 1, or 2"); ++ return FALSE; + } +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_getter_ifname - Get interface name +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a name of network interface +- * associated with with wpa_s ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Ifname" property. + */ +-DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { ++ struct wpa_supplicant *wpa_s = user_data; + const char *ifname = wpa_s->ifname; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &ifname); ++ ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &ifname, error); + } + + + /** + * wpas_dbus_getter_driver - Get interface name +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a name of network interface +- * driver associated with with wpa_s +++ * @iter: Pointer to incoming dbus message iter +++ * @error: Location to store error on failure +++ * @user_data: Function specific data +++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Driver" property. + */ +-DBusMessage * wpas_dbus_getter_driver(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { ++ struct wpa_supplicant *wpa_s = user_data; + const char *driver; + + if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { + wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: " + "wpa_s has no driver set"); +- return wpas_dbus_error_unknown_error(message, NULL); ++ dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set", ++ __func__); ++ return FALSE; + } + + driver = wpa_s->driver->name; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &driver); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &driver, error); + } + + + /** + * wpas_dbus_getter_current_bss - Get current bss object path +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a DBus object path to +- * current BSS ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "CurrentBSS" property. + */ +-DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- DBusMessage *reply; ++ struct wpa_supplicant *wpa_s = user_data; + char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; + + if (wpa_s->current_bss) +@@ -2135,27 +2118,25 @@ DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message, + else + os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); + +- reply = wpas_dbus_simple_property_getter(message, +- DBUS_TYPE_OBJECT_PATH, +- &bss_obj_path); +- +- return reply; ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, ++ &bss_obj_path, error); + } + + + /** + * wpas_dbus_getter_current_network - Get current network object path +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a DBus object path to +- * current network ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "CurrentNetwork" property. + */ +-DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- DBusMessage *reply; ++ struct wpa_supplicant *wpa_s = user_data; + char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; + + if (wpa_s->current_ssid) +@@ -2165,70 +2146,63 @@ DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message, + else + os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); + +- reply = wpas_dbus_simple_property_getter(message, +- DBUS_TYPE_OBJECT_PATH, +- &net_obj_path); +- +- return reply; ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, ++ &net_obj_path, error); + } + + + /** + * wpas_dbus_getter_bridge_ifname - Get interface name +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: A dbus message containing a name of bridge network +- * interface associated with with wpa_s ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "BridgeIfname" property. + */ +-DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- const char *bridge_ifname = NULL; +- +- bridge_ifname = wpa_s->bridge_ifname; +- if (bridge_ifname == NULL) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: " +- "wpa_s has no bridge interface name set"); +- return wpas_dbus_error_unknown_error(message, NULL); +- } ++ struct wpa_supplicant *wpa_s = user_data; ++ const char *bridge_ifname; + +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &bridge_ifname); ++ bridge_ifname = wpa_s->bridge_ifname ? wpa_s->bridge_ifname : ""; ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &bridge_ifname, error); + } + + + /** + * wpas_dbus_getter_bsss - Get array of BSSs objects +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: a dbus message containing an array of all known BSS objects +- * dbus paths ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "BSSs" property. + */ +-DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + struct wpa_bss *bss; + char **paths; + unsigned int i = 0; ++ dbus_bool_t success = FALSE; + + paths = os_zalloc(wpa_s->num_bss * sizeof(char *)); + if (!paths) { +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + /* Loop through scan results and append each result's object path */ + dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { + paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); + if (paths[i] == NULL) { +- reply = dbus_message_new_error(message, +- DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, ++ "no memory"); + goto out; + } + /* Construct the object path for this BSS. */ +@@ -2237,39 +2211,43 @@ DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message, + wpa_s->dbus_new_path, bss->id); + } + +- reply = wpas_dbus_simple_array_property_getter(message, +- DBUS_TYPE_OBJECT_PATH, +- paths, wpa_s->num_bss); ++ success = wpas_dbus_simple_array_property_getter(iter, ++ DBUS_TYPE_OBJECT_PATH, ++ paths, wpa_s->num_bss, ++ error); + + out: + while (i) + os_free(paths[--i]); + os_free(paths); +- return reply; ++ return TRUE; + } + + + /** + * wpas_dbus_getter_networks - Get array of networks objects +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: a dbus message containing an array of all configured +- * networks dbus object paths. ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Networks" property. + */ +-DBusMessage * wpas_dbus_getter_networks(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + struct wpa_ssid *ssid; + char **paths; + unsigned int i = 0, num = 0; ++ dbus_bool_t success = FALSE; + + if (wpa_s->conf == NULL) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: " +- "An error occurred getting networks list."); +- return wpas_dbus_error_unknown_error(message, NULL); ++ wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting " ++ "networks list.", __func__); ++ dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error " ++ "occurred getting the networks list", __func__); ++ return FALSE; + } + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) +@@ -2277,17 +2255,15 @@ DBusMessage * wpas_dbus_getter_networks(DBusMessage *message, + + paths = os_zalloc(num * sizeof(char *)); + if (!paths) { +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + /* Loop through configured networks and append object path of each */ + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); + if (paths[i] == NULL) { +- reply = dbus_message_new_error(message, +- DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); + goto out; + } + +@@ -2297,50 +2273,40 @@ DBusMessage * wpas_dbus_getter_networks(DBusMessage *message, + wpa_s->dbus_new_path, ssid->id); + } + +- reply = wpas_dbus_simple_array_property_getter(message, +- DBUS_TYPE_OBJECT_PATH, +- paths, num); ++ success = wpas_dbus_simple_array_property_getter(iter, ++ DBUS_TYPE_OBJECT_PATH, ++ paths, num, error); + + out: + while (i) + os_free(paths[--i]); + os_free(paths); +- return reply; ++ return success; + } + + + /** + * wpas_dbus_getter_blobs - Get all blobs defined for this interface +- * @message: Pointer to incoming dbus message +- * @wpa_s: wpa_supplicant structure for a network interface +- * Returns: a dbus message containing a dictionary of pairs (blob_name, blob) ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Blobs" property. + */ +-DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message, +- struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; +- DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter; ++ struct wpa_supplicant *wpa_s = user_data; ++ DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; + struct wpa_config_blob *blob; + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- if (!reply) +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); +- +- dbus_message_iter_init_append(reply, &iter); +- +- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + "a{say}", &variant_iter) || + !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, + "{say}", &dict_iter)) { +- dbus_message_unref(reply); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + blob = wpa_s->conf->blobs; +@@ -2363,176 +2329,189 @@ DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message, + &array_iter) || + !dbus_message_iter_close_container(&dict_iter, + &entry_iter)) { +- dbus_message_unref(reply); +- return dbus_message_new_error(message, +- DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, ++ "no memory"); ++ return FALSE; + } + + blob = blob->next; + } + + if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || +- !dbus_message_iter_close_container(&iter, &variant_iter)) { +- dbus_message_unref(reply); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ !dbus_message_iter_close_container(iter, &variant_iter)) { ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + +- return reply; ++ return TRUE; + } + ++static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, ++ DBusError *error, ++ const char *func_name) ++{ ++ struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id); ++ ++ if (!res) { ++ wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found", ++ func_name, args->id); ++ dbus_set_error(error, DBUS_ERROR_FAILED, "%s: BSS %d not found", ++ func_name, args->id); ++ } ++ return res; ++} + + /** + * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the bssid for the requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "BSSID" property. + */ +-DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + +- return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, +- res->bssid, ETH_ALEN); ++ return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, ++ res->bssid, ETH_ALEN, ++ error); + } + + + /** + * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the ssid for the requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "SSID" property. + */ +-DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + +- return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, +- res->ssid, +- res->ssid_len); ++ return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, ++ res->ssid, res->ssid_len, ++ error); + } + + + /** + * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the privacy flag value of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Privacy" property. + */ +-DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + dbus_bool_t privacy; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + + privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &privacy); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &privacy, error); + } + + + /** + * wpas_dbus_getter_bss_mode - Return the mode of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the mode of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Mode" property. + */ +-DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + const char *mode; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + + if (res->caps & IEEE80211_CAP_IBSS) + mode = "ad-hoc"; + else + mode = "infrastructure"; + +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, +- &mode); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, ++ &mode, error); + } + + + /** + * wpas_dbus_getter_bss_level - Return the signal strength of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the signal strength of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Level" property. + */ +-DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16, +- &res->level); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, ++ &res->level, error); + } + + + /** + * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the frequency of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Frequency" property. + */ +-DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: " +- "no bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16, +- &res->freq); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, ++ &res->freq, error); + } + + +@@ -2544,72 +2523,64 @@ static int cmp_u8s_desc(const void *a, const void *b) + + /** + * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing sorted array of bit rates ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Rates" property. + */ +-DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- DBusMessage *reply; +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + u8 *ie_rates = NULL; + u32 *real_rates; + int rates_num, i; ++ dbus_bool_t success = FALSE; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: " +- "no bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + + rates_num = wpa_bss_get_bit_rates(res, &ie_rates); + if (rates_num < 0) +- return NULL; ++ return FALSE; + + qsort(ie_rates, rates_num, 1, cmp_u8s_desc); + + real_rates = os_malloc(sizeof(u32) * rates_num); + if (!real_rates) { + os_free(ie_rates); +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + for (i = 0; i < rates_num; i++) + real_rates[i] = ie_rates[i] * 500000; + +- reply = wpas_dbus_simple_array_property_getter(message, +- DBUS_TYPE_UINT32, +- real_rates, rates_num); ++ success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32, ++ real_rates, rates_num, ++ error); + + os_free(ie_rates); + os_free(real_rates); +- return reply; ++ return success; + } + + +-static DBusMessage * wpas_dbus_get_bss_security_prop( +- DBusMessage *message, struct wpa_ie_data *ie_data) ++static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, ++ struct wpa_ie_data *ie_data, ++ DBusError *error) + { +- DBusMessage *reply; +- DBusMessageIter iter, iter_dict, variant_iter; ++ DBusMessageIter iter_dict, variant_iter; + const char *group; + const char *pairwise[2]; /* max 2 pairwise ciphers is supported */ + const char *key_mgmt[7]; /* max 7 key managements may be supported */ + int n; + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- if (!reply) +- goto nomem; +- +- dbus_message_iter_init_append(reply, &iter); +- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + "a{sv}", &variant_iter)) + goto nomem; + +@@ -2690,152 +2661,152 @@ static DBusMessage * wpas_dbus_get_bss_security_prop( + + if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) + goto nomem; +- if (!dbus_message_iter_close_container(&iter, &variant_iter)) ++ if (!dbus_message_iter_close_container(iter, &variant_iter)) + goto nomem; + +- return reply; ++ return TRUE; + + nomem: +- if (reply) +- dbus_message_unref(reply); +- +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + + + /** + * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the WPA options of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "WPA" property. + */ +-DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + struct wpa_ie_data wpa_data; + const u8 *ie; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + + os_memset(&wpa_data, 0, sizeof(wpa_data)); + ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); + if (ie) { +- if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) +- return wpas_dbus_error_unknown_error(message, +- "invalid WPA IE"); ++ if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, ++ "failed to parse WPA IE"); ++ return FALSE; ++ } + } + +- return wpas_dbus_get_bss_security_prop(message, &wpa_data); ++ return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); + } + + + /** + * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing the RSN options of requested bss ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "RSN" property. + */ +-DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + struct wpa_ie_data wpa_data; + const u8 *ie; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + + os_memset(&wpa_data, 0, sizeof(wpa_data)); + ie = wpa_bss_get_ie(res, WLAN_EID_RSN); + if (ie) { +- if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) +- return wpas_dbus_error_unknown_error(message, +- "invalid RSN IE"); ++ if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { ++ dbus_set_error_const(error, DBUS_ERROR_FAILED, ++ "failed to parse RSN IE"); ++ return FALSE; ++ } + } + +- return wpas_dbus_get_bss_security_prop(message, &wpa_data); ++ return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); + } + + + /** + * wpas_dbus_getter_bss_ies - Return all IEs of a BSS +- * @message: Pointer to incoming dbus message +- * @bss: a pair of interface describing structure and bss's id +- * Returns: a dbus message containing IEs byte array ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "IEs" property. + */ +-DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message, +- struct bss_handler_args *bss) ++dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); ++ struct bss_handler_args *args = user_data; ++ struct wpa_bss *res; + +- if (!res) { +- wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no " +- "bss with id %d found", bss->id); +- return NULL; +- } ++ res = get_bss_helper(args, error, __func__); ++ if (!res) ++ return FALSE; + +- return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, +- res + 1, res->ie_len); ++ return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, ++ res + 1, res->ie_len, ++ error); + } + + + /** + * wpas_dbus_getter_enabled - Check whether network is enabled or disabled +- * @message: Pointer to incoming dbus message +- * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface +- * and wpa_ssid structure for a configured network +- * Returns: DBus message with boolean indicating state of configured network +- * or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "enabled" property of a configured network. + */ +-DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message, +- struct network_handler_args *net) ++dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { ++ struct network_handler_args *net = user_data; + dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &enabled); ++ ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &enabled, error); + } + + + /** + * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled +- * @message: Pointer to incoming dbus message +- * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface +- * and wpa_ssid structure for a configured network +- * Returns: NULL indicating success or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "Enabled" property of a configured network. + */ +-DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message, +- struct network_handler_args *net) ++dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; +- ++ struct network_handler_args *net = user_data; + struct wpa_supplicant *wpa_s; + struct wpa_ssid *ssid; +- + dbus_bool_t enable; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, +- &enable); +- +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, ++ &enable)) ++ return FALSE; + + wpa_s = net->wpa_s; + ssid = net->ssid; +@@ -2845,48 +2816,37 @@ DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message, + else + wpa_supplicant_disable_network(wpa_s, ssid); + +- return NULL; ++ return TRUE; + } + + + /** + * wpas_dbus_getter_network_properties - Get options for a configured network +- * @message: Pointer to incoming dbus message +- * @net: wpa_supplicant structure for a network interface and +- * wpa_ssid structure for a configured network +- * Returns: DBus message with network properties or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Getter for "Properties" property of a configured network. + */ +-DBusMessage * wpas_dbus_getter_network_properties( +- DBusMessage *message, struct network_handler_args *net) ++dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { +- DBusMessage *reply = NULL; +- DBusMessageIter iter, variant_iter, dict_iter; ++ struct network_handler_args *net = user_data; ++ DBusMessageIter variant_iter, dict_iter; + char **iterator; + char **props = wpa_config_get_all(net->ssid, 0); +- if (!props) +- return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_bool_t success = FALSE; + +- if (message == NULL) +- reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); +- else +- reply = dbus_message_new_method_return(message); +- if (!reply) { +- reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); +- goto out; ++ if (!props) { ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); ++ return FALSE; + } + +- dbus_message_iter_init_append(reply, &iter); +- +- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, +- "a{sv}", &variant_iter) || ++ if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", ++ &variant_iter) || + !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { +- dbus_message_unref(reply); +- reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + goto out; + } + +@@ -2894,10 +2854,8 @@ DBusMessage * wpas_dbus_getter_network_properties( + while (*iterator) { + if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, + *(iterator + 1))) { +- dbus_message_unref(reply); +- reply = dbus_message_new_error(message, +- DBUS_ERROR_NO_MEMORY, +- NULL); ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, ++ "no memory"); + goto out; + } + iterator += 2; +@@ -2905,13 +2863,13 @@ DBusMessage * wpas_dbus_getter_network_properties( + + + if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || +- !dbus_message_iter_close_container(&iter, &variant_iter)) { +- dbus_message_unref(reply); +- reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, +- NULL); ++ !dbus_message_iter_close_container(iter, &variant_iter)) { ++ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); + goto out; + } + ++ success = TRUE; ++ + out: + iterator = props; + while (*iterator) { +@@ -2919,39 +2877,27 @@ out: + iterator++; + } + os_free(props); +- return reply; ++ return success; + } + + + /** + * wpas_dbus_setter_network_properties - Set options for a configured network +- * @message: Pointer to incoming dbus message +- * @net: wpa_supplicant structure for a network interface and +- * wpa_ssid structure for a configured network +- * Returns: NULL indicating success or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "Properties" property of a configured network. + */ +-DBusMessage * wpas_dbus_setter_network_properties( +- DBusMessage *message, struct network_handler_args *net) ++dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { ++ struct network_handler_args *net = user_data; + struct wpa_ssid *ssid = net->ssid; ++ DBusMessageIter variant_iter; + +- DBusMessage *reply = NULL; +- DBusMessageIter iter, variant_iter; +- +- dbus_message_iter_init(message, &iter); +- +- dbus_message_iter_next(&iter); +- dbus_message_iter_next(&iter); +- +- dbus_message_iter_recurse(&iter, &variant_iter); +- +- reply = set_network_properties(message, net->wpa_s, ssid, +- &variant_iter); +- if (reply) +- wpa_printf(MSG_DEBUG, "dbus control interface couldn't set " +- "network properties"); +- +- return reply; ++ dbus_message_iter_recurse(iter, &variant_iter); ++ return set_network_properties(net->wpa_s, ssid, &variant_iter, error); + } +diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h +index 3cdf9cb..9d5b6ff 100644 +--- a/wpa_supplicant/dbus/dbus_new_handlers.h ++++ b/wpa_supplicant/dbus/dbus_new_handlers.h +@@ -26,17 +26,20 @@ struct bss_handler_args { + unsigned int id; + }; + +-DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message, +- const int type, +- const void *val); ++dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter, ++ const int type, ++ const void *val, ++ DBusError *error); + +-DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message, +- const int type, void *val); ++dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter, ++ DBusError *error, ++ const int type, void *val); + +-DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message, +- const int type, +- const void *array, +- size_t array_len); ++dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter, ++ const int type, ++ const void *array, ++ size_t array_len, ++ DBusError *error); + + DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, + struct wpa_global *global); +@@ -47,29 +50,34 @@ DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message, + DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message, + struct wpa_global *global); + +-DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message, +- struct wpa_global *global); ++dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, +- void *nothing); ++dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + + DBusMessage * wpas_dbus_handler_scan(DBusMessage *message, + struct wpa_supplicant *wpa_s); +@@ -95,98 +103,122 @@ DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message, + DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +-DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_state(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_driver(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_networks(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message, +- struct wpa_supplicant *bss); ++dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message, +- struct bss_handler_args *bss); ++dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message, +- struct network_handler_args *net); ++dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message, +- struct network_handler_args *net); ++dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_getter_network_properties( +- DBusMessage *message, struct network_handler_args *net); ++dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error, ++ void *user_data); + +-DBusMessage * wpas_dbus_setter_network_properties( +- DBusMessage *message, struct network_handler_args *net); ++dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); ++ ++dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + + DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +-DBusMessage * wpas_dbus_getter_process_credentials( +- DBusMessage *message, struct wpa_supplicant *wpa_s); +- +-DBusMessage * wpas_dbus_setter_process_credentials( +- DBusMessage *message, struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter, ++ DBusError *error, void *user_data); + +-DBusMessage * wpas_dbus_getter_credentials(DBusMessage *message, +- struct wpa_supplicant *wpa_s); ++dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + + DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message, + const char *arg); +diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c +index dc44a59..9e934c7 100644 +--- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c ++++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c +@@ -289,34 +289,36 @@ DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message, + * true if wps_cred_processing configuration field is not equal to 1 or false + * if otherwise. + */ +-DBusMessage * wpas_dbus_getter_process_credentials( +- DBusMessage *message, struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter, ++ DBusError *error, void *user_data) + { ++ struct wpa_supplicant *wpa_s = user_data; + dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1); +- return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, +- &process); ++ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, ++ &process, error); + } + + + /** + * wpas_dbus_setter_process_credentials - Set credentials_processed conf param +- * @message: Pointer to incoming dbus message +- * @wpa_s: %wpa_supplicant data structure +- * Returns: NULL on success or DBus error on failure ++ * @iter: Pointer to incoming dbus message iter ++ * @error: Location to store error on failure ++ * @user_data: Function specific data ++ * Returns: TRUE on success, FALSE on failure + * + * Setter for "ProcessCredentials" property. Sets credentials_processed on 2 + * if boolean argument is true or on 1 if otherwise. + */ +-DBusMessage * wpas_dbus_setter_process_credentials( +- DBusMessage *message, struct wpa_supplicant *wpa_s) ++dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data) + { +- DBusMessage *reply = NULL; ++ struct wpa_supplicant *wpa_s = user_data; + dbus_bool_t process_credentials, old_pc; + +- reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, +- &process_credentials); +- if (reply) +- return reply; ++ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, ++ &process_credentials)) ++ return FALSE; + + old_pc = (wpa_s->conf->wps_cred_processing != 1); + wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1); +@@ -327,5 +329,5 @@ DBusMessage * wpas_dbus_setter_process_credentials( + WPAS_DBUS_NEW_IFACE_WPS, + "ProcessCredentials"); + +- return NULL; ++ return TRUE; + } +diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c +index 06749db..e77a0c7 100644 +--- a/wpa_supplicant/dbus/dbus_new_helpers.c ++++ b/wpa_supplicant/dbus/dbus_new_helpers.c +@@ -21,112 +21,49 @@ + #include "dbus_common_i.h" + #include "dbus_new.h" + #include "dbus_new_helpers.h" ++#include "dbus_dict_helpers.h" + + +-/** +- * 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) + { +- +- 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; + const struct wpa_dbus_property_desc *dsc; + + for (dsc = props; dsc && dsc->dbus_property; dsc++) { +- 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; +- +- if (dbus_message_get_type(reply) == +- DBUS_MESSAGE_TYPE_ERROR) { +- dbus_message_unref(reply); +- continue; +- } ++ /* Only return properties for the requested D-Bus interface */ ++ if (os_strncmp(dsc->dbus_interface, interface, ++ WPAS_DBUS_INTERFACE_MAX) != 0) ++ continue; + +- dbus_message_iter_init(reply, &ret_iter); ++ /* Handle access permissions or missing getter */ ++ if (dsc->getter == NULL || dsc->access == W) ++ continue; + +- 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); ++ 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; ++ } + +- recursive_iter_copy(&ret_iter, &entry_iter); ++ /* An error getting a property fails the request entirely */ ++ if (!dsc->getter(&entry_iter, error, user_data)) ++ return FALSE; + +- dbus_message_iter_close_container(dict_iter, +- &entry_iter); +- dbus_message_unref(reply); +- counter++; +- } ++ dbus_message_iter_close_container(dict_iter, &entry_iter); + } + +- return counter; ++ return TRUE; + } + + +@@ -142,37 +79,43 @@ static unsigned int fill_dict_with_properties( + * specified as argument. Returned message contains one dict argument + * with properties names as keys and theirs values as values. + */ +-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) + { +- /* Create and initialize the return message */ +- DBusMessage *reply = dbus_message_new_method_return(message); ++ DBusMessage *reply; + DBusMessageIter iter, dict_iter; +- int props_num; +- +- dbus_message_iter_init_append(reply, &iter); +- +- 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); ++ DBusError error; + +- props_num = fill_dict_with_properties(&dict_iter, obj_dsc->properties, +- interface, obj_dsc->user_data); ++ reply = dbus_message_new_method_return(message); ++ if (reply == NULL) { ++ wpa_printf(MSG_ERROR, "%s: out of memory creating dbus reply", ++ __func__); ++ return NULL; ++ } + +- dbus_message_iter_close_container(&iter, &dict_iter); ++ dbus_message_iter_init_append(reply, &iter); ++ 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; ++ } + +- if (props_num == 0) { ++ dbus_error_init(&error); ++ if (!fill_dict_with_properties(&dict_iter, obj_dsc->properties, ++ interface, obj_dsc->user_data, &error)) { + dbus_message_unref(reply); +- 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; + } + ++ wpa_dbus_dict_close_write(&iter, &dict_iter); + return reply; + } + +@@ -219,15 +162,33 @@ static DBusMessage * properties_get(DBusMessage *message, + const struct wpa_dbus_property_desc *dsc, + void *user_data) + { +- if (os_strcmp(dbus_message_get_signature(message), "ss")) ++ DBusMessage *reply; ++ DBusMessageIter iter; ++ DBusError error; ++ ++ if (os_strcmp(dbus_message_get_signature(message), "ss")) { + return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + NULL); ++ } ++ ++ if (dsc->access == W || dsc->getter == NULL) { ++ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, ++ "Property is write-only"); ++ } + +- if (dsc->access != W && dsc->getter) +- return dsc->getter(message, user_data); ++ reply = dbus_message_new_method_return(message); ++ dbus_message_iter_init_append(reply, &iter); + +- return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, +- "Property is write-only"); ++ 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; + } + + +@@ -235,15 +196,38 @@ static DBusMessage * properties_set(DBusMessage *message, + const struct wpa_dbus_property_desc *dsc, + void *user_data) + { +- if (os_strcmp(dbus_message_get_signature(message), "ssv")) ++ DBusMessage *reply; ++ DBusMessageIter iter; ++ DBusError error; ++ ++ if (os_strcmp(dbus_message_get_signature(message), "ssv")) { + return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + NULL); ++ } ++ ++ if (dsc->access == R || dsc->setter == NULL) { ++ 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); + +- if (dsc->access != R && dsc->setter) +- return dsc->setter(message, user_data); ++ /* 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 dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, +- "Property is read-only"); ++ return reply; + } + + +@@ -611,14 +595,14 @@ int wpa_dbus_unregister_object_per_iface( + } + + +-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) + { +- DBusMessage *getter_reply; +- DBusMessageIter prop_iter, entry_iter; ++ DBusMessageIter entry_iter; + const struct wpa_dbus_property_desc *dsc; + int i; ++ DBusError error; + + for (dsc = obj_dsc->properties, i = 0; dsc && dsc->dbus_property; + dsc++, i++) { +@@ -629,37 +613,37 @@ static void put_changed_properties(const struct wpa_dbus_object_desc *obj_dsc, + continue; + obj_dsc->prop_changed_flags[i] = 0; + +- 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, + DBUS_TYPE_DICT_ENTRY, +- NULL, &entry_iter) || +- !dbus_message_iter_append_basic(&entry_iter, ++ NULL, &entry_iter)) ++ return FALSE; ++ ++ if (!dbus_message_iter_append_basic(&entry_iter, + DBUS_TYPE_STRING, + &dsc->dbus_property)) +- goto err; +- +- recursive_iter_copy(&prop_iter, &entry_iter); ++ return FALSE; ++ ++ 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; ++ } + + if (!dbus_message_iter_close_container(dict_iter, &entry_iter)) +- goto err; +- +- dbus_message_unref(getter_reply); ++ return FALSE; + } + +- return; +- +-err: +- wpa_printf(MSG_ERROR, "dbus: %s: Cannot construct signal", __func__); ++ return TRUE; + } + + +@@ -680,7 +664,8 @@ static void send_prop_changed_signal( + "{sv}", &dict_iter)) + goto err; + +- put_changed_properties(obj_dsc, interface, &dict_iter); ++ if (!put_changed_properties(obj_dsc, interface, &dict_iter)) ++ goto err; + + if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) + goto err; +@@ -849,27 +834,75 @@ void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface, + * @iface: dbus priv struct + * @path: path to DBus object which properties will be obtained + * @interface: interface name which properties will be obtained +- * @dict_iter: correct, open DBus dictionary iterator. ++ * @iter: DBus message iter at which to append property dictionary. + * + * Iterates over all properties registered with object and execute getters + * of those, which are readable and which interface matches interface + * specified as argument. Obtained properties values are stored in + * dict_iter dictionary. + */ +-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) + { + struct wpa_dbus_object_desc *obj_desc = NULL; ++ DBusMessageIter dict_iter; ++ DBusError error; + + dbus_connection_get_object_path_data(iface->con, path, + (void **) &obj_desc); + if (!obj_desc) { +- 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; ++ } ++ ++ 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; + } + +- fill_dict_with_properties(dict_iter, obj_desc->properties, +- interface, obj_desc->user_data); ++ return wpa_dbus_dict_close_write(iter, &dict_iter); ++} ++ ++/** ++ * 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; + } +diff --git a/wpa_supplicant/dbus/dbus_new_helpers.h b/wpa_supplicant/dbus/dbus_new_helpers.h +index 8db7a37..32a3ba5 100644 +--- a/wpa_supplicant/dbus/dbus_new_helpers.h ++++ b/wpa_supplicant/dbus/dbus_new_helpers.h +@@ -22,8 +22,9 @@ typedef DBusMessage * (* WPADBusMethodHandler)(DBusMessage *message, + void *user_data); + typedef void (* WPADBusArgumentFreeFunction)(void *handler_arg); + +-typedef DBusMessage * (* WPADBusPropertyAccessor)(DBusMessage *message, +- const void *user_data); ++typedef dbus_bool_t (* WPADBusPropertyAccessor)(DBusMessageIter *iter, ++ DBusError *error, ++ void *user_data); + + struct wpa_dbus_object_desc { + DBusConnection *connection; +@@ -127,9 +128,10 @@ int wpa_dbus_unregister_object_per_iface( + struct wpas_dbus_priv *ctrl_iface, + const char *path); + +-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); + + + void wpa_dbus_flush_all_changed_properties(DBusConnection *con); +@@ -144,4 +146,9 @@ void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface, + DBusMessage * wpa_dbus_introspect(DBusMessage *message, + struct wpa_dbus_object_desc *obj_dsc); + ++DBusMessage *wpas_dbus_reply_new_from_error(DBusMessage *message, ++ DBusError *error, ++ const char *fallback_name, ++ const char *fallback_string); ++ + #endif /* WPA_DBUS_CTRL_H */ +diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c +index d914697..3d252e7 100644 +--- a/wpa_supplicant/dbus/dbus_old_handlers.c ++++ b/wpa_supplicant/dbus/dbus_old_handlers.c +@@ -116,7 +116,7 @@ DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, + DBusMessageIter iter_dict; + struct wpa_dbus_dict_entry entry; + +- if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) ++ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) + goto error; + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { + if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) +@@ -922,7 +922,7 @@ DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, + + dbus_message_iter_init(message, &iter); + +- if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) { ++ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) { + reply = wpas_dbus_new_invalid_opts_error(message, NULL); + goto out; + } +@@ -1202,7 +1202,7 @@ DBusMessage * wpas_dbus_iface_set_smartcard_modules( + if (!dbus_message_iter_init(message, &iter)) + goto error; + +- if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) ++ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) + goto error; + + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { +@@ -1324,7 +1324,7 @@ DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, + + dbus_message_iter_init(message, &iter); + +- if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) ++ if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) + return wpas_dbus_new_invalid_opts_error(message, NULL); + + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { +-- +1.7.4.4 + diff --git a/wpa_supplicant-dbus-null-error.patch b/wpa_supplicant-dbus-null-error.patch deleted file mode 100644 index ede6006..0000000 --- a/wpa_supplicant-dbus-null-error.patch +++ /dev/null @@ -1,47 +0,0 @@ -commit 8ee69e06336d65b15364f4db82d91775d0fe47c6 -Author: Paul Stewart -Date: Sat Oct 9 17:29:51 2010 +0300 - - dbus_new_handlers: Don't send NULL to dbus_message_new_error - - The new DBus API helper function wpas_dbus_error_unknown_error - function can be called as a result of a failure within internal - getter calls, which will call this function with a NULL message - parameter. However, dbus_message_new_error looks very unkindly - (i.e, abort()) on a NULL message, so in this case, we should not - call it. - - I've observed this course of events during a call to - wpas_dbus_getter_bss_wpa with a faileld parse of the IE parameter. - We got here through a call to fill_dict_with_properties which - explicitly calls getters with a NULL message parameter. Judging - from the way it is called, this could easily occur if an AP sends - out a malformed (or mis-received) probe response. I usually run - into this problem while driving through San Francisco, so I'm - exposed to any number of base stations along this path. - -diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c -index 73f4e44..0ad51a0 100644 ---- a/wpa_supplicant/dbus/dbus_new_handlers.c -+++ b/wpa_supplicant/dbus/dbus_new_handlers.c -@@ -117,6 +117,20 @@ static char * wpas_dbus_new_decompose_object_path(const char *path, - DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message, - const char *arg) - { -+ /* -+ * This function can be called as a result of a failure -+ * within internal getter calls, which will call this function -+ * with a NULL message parameter. However, dbus_message_new_error -+ * looks very unkindly (i.e, abort()) on a NULL message, so -+ * in this case, we should not call it. -+ */ -+ if (message == NULL) { -+ wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error " -+ "called with NULL message (arg=%s)", -+ arg ? arg : "N/A"); -+ return NULL; -+ } -+ - return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR, - arg); - } diff --git a/wpa_supplicant.spec b/wpa_supplicant.spec index f0ca4fc..1ff1803 100644 --- a/wpa_supplicant.spec +++ b/wpa_supplicant.spec @@ -2,7 +2,7 @@ Summary: WPA/WPA2/IEEE 802.1X Supplicant Name: wpa_supplicant Epoch: 1 Version: 0.7.3 -Release: 8%{?dist} +Release: 9%{?dist} License: BSD Group: System Environment/Base Source0: http://w1.fi/releases/%{name}-%{version}.tar.gz @@ -36,7 +36,7 @@ Patch6: wpa_supplicant-gui-qt4.patch # Send PropertyChanged notificationes when the BSS list changes Patch7: wpa_supplicant-bss-changed-prop-notify.patch # Don't crash trying to pass NULL to dbus -Patch8: wpa_supplicant-dbus-null-error.patch +Patch8: 0001-dbus-clean-up-new-D-Bus-interface-getters-setters.patch # Dirty hack for WiMAX # http://linuxwimax.org/Download?action=AttachFile&do=get&target=wpa-1.5-README.txt Patch100: wpa_supplicant-0.7.2-generate-libeap-peer.patch @@ -97,7 +97,7 @@ Don't use this unless you know what you're doing. %patch5 -p1 -b .more-openssl-algs %patch6 -p1 -b .qt4 %patch7 -p1 -b .bss-changed-prop-notify -%patch8 -p1 -b .dbus-null +%patch8 -p1 -b .dbus-rework %build pushd wpa_supplicant @@ -214,6 +214,9 @@ fi %postun -n libeap -p /sbin/ldconfig %changelog +* Wed Jul 27 2011 Dan Williams - 1:0.7.3-9 +- Fix various crashes with D-Bus interface (rh #678625) (rh #725517) + * Tue May 3 2011 Dan Williams - 1:0.7.3-8 - Don't crash when trying to access invalid properties via D-Bus (rh #678625)