Home | History | Annotate | Download | only in dbus
      1 /*
      2  * WPA Supplicant / dbus-based control interface
      3  * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc.
      4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa (at) gmail.com>
      5  * Copyright (c) 2009-2015, Jouni Malinen <j (at) w1.fi>
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "includes.h"
     12 
     13 #include "common.h"
     14 #include "common/ieee802_11_defs.h"
     15 #include "eap_peer/eap_methods.h"
     16 #include "eapol_supp/eapol_supp_sm.h"
     17 #include "rsn_supp/wpa.h"
     18 #include "../config.h"
     19 #include "../wpa_supplicant_i.h"
     20 #include "../driver_i.h"
     21 #include "../notify.h"
     22 #include "../bss.h"
     23 #include "../scan.h"
     24 #include "../autoscan.h"
     25 #include "dbus_new_helpers.h"
     26 #include "dbus_new.h"
     27 #include "dbus_new_handlers.h"
     28 #include "dbus_dict_helpers.h"
     29 #include "dbus_common_i.h"
     30 #include "drivers/driver.h"
     31 #ifdef CONFIG_MESH
     32 #include "ap/hostapd.h"
     33 #include "ap/sta_info.h"
     34 #endif /* CONFIG_MESH */
     35 
     36 static const char * const debug_strings[] = {
     37 	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
     38 };
     39 
     40 
     41 /**
     42  * wpas_dbus_error_unknown_error - Return a new UnknownError error message
     43  * @message: Pointer to incoming dbus message this error refers to
     44  * @arg: Optional string appended to error message
     45  * Returns: a dbus error message
     46  *
     47  * Convenience function to create and return an UnknownError
     48  */
     49 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
     50 					    const char *arg)
     51 {
     52 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
     53 				      arg);
     54 }
     55 
     56 
     57 /**
     58  * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
     59  * @message: Pointer to incoming dbus message this error refers to
     60  * Returns: A dbus error message
     61  *
     62  * Convenience function to create and return an invalid interface error
     63  */
     64 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
     65 {
     66 	return dbus_message_new_error(
     67 		message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
     68 		"wpa_supplicant knows nothing about this interface.");
     69 }
     70 
     71 
     72 /**
     73  * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
     74  * @message: Pointer to incoming dbus message this error refers to
     75  * Returns: a dbus error message
     76  *
     77  * Convenience function to create and return an invalid network error
     78  */
     79 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
     80 {
     81 	return dbus_message_new_error(
     82 		message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
     83 		"There is no such a network in this interface.");
     84 }
     85 
     86 
     87 /**
     88  * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
     89  * @message: Pointer to incoming dbus message this error refers to
     90  * Returns: a dbus error message
     91  *
     92  * Convenience function to create and return an invalid options error
     93  */
     94 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
     95 					  const char *arg)
     96 {
     97 	DBusMessage *reply;
     98 
     99 	reply = dbus_message_new_error(
    100 		message, WPAS_DBUS_ERROR_INVALID_ARGS,
    101 		"Did not receive correct message arguments.");
    102 	if (arg != NULL)
    103 		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
    104 					 DBUS_TYPE_INVALID);
    105 
    106 	return reply;
    107 }
    108 
    109 
    110 /**
    111  * wpas_dbus_error_scan_error - Return a new ScanError error message
    112  * @message: Pointer to incoming dbus message this error refers to
    113  * @error: Optional string to be used as the error message
    114  * Returns: a dbus error message
    115  *
    116  * Convenience function to create and return a scan error
    117  */
    118 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message,
    119 						const char *error)
    120 {
    121 	return dbus_message_new_error(message,
    122 				      WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
    123 				      error);
    124 }
    125 
    126 
    127 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
    128 {
    129 	wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory");
    130 	return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
    131 }
    132 
    133 
    134 static const char * const dont_quote[] = {
    135 	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
    136 	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
    137 	"bssid", "scan_freq", "freq_list", NULL
    138 };
    139 
    140 static dbus_bool_t should_quote_opt(const char *key)
    141 {
    142 	int i = 0;
    143 
    144 	while (dont_quote[i] != NULL) {
    145 		if (os_strcmp(key, dont_quote[i]) == 0)
    146 			return FALSE;
    147 		i++;
    148 	}
    149 	return TRUE;
    150 }
    151 
    152 /**
    153  * get_iface_by_dbus_path - Get a new network interface
    154  * @global: Pointer to global data from wpa_supplicant_init()
    155  * @path: Pointer to a dbus object path representing an interface
    156  * Returns: Pointer to the interface or %NULL if not found
    157  */
    158 static struct wpa_supplicant * get_iface_by_dbus_path(
    159 	struct wpa_global *global, const char *path)
    160 {
    161 	struct wpa_supplicant *wpa_s;
    162 
    163 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    164 		if (wpa_s->dbus_new_path &&
    165 		    os_strcmp(wpa_s->dbus_new_path, path) == 0)
    166 			return wpa_s;
    167 	}
    168 	return NULL;
    169 }
    170 
    171 
    172 /**
    173  * set_network_properties - Set properties of a configured network
    174  * @wpa_s: wpa_supplicant structure for a network interface
    175  * @ssid: wpa_ssid structure for a configured network
    176  * @iter: DBus message iterator containing dictionary of network
    177  * properties to set.
    178  * @error: On failure, an error describing the failure
    179  * Returns: TRUE if the request succeeds, FALSE if it failed
    180  *
    181  * Sets network configuration with parameters given id DBus dictionary
    182  */
    183 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
    184 				   struct wpa_ssid *ssid,
    185 				   DBusMessageIter *iter,
    186 				   DBusError *error)
    187 {
    188 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
    189 	DBusMessageIter	iter_dict;
    190 	char *value = NULL;
    191 
    192 	if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
    193 		return FALSE;
    194 
    195 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    196 		size_t size = 50;
    197 		int ret;
    198 
    199 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    200 			goto error;
    201 
    202 		value = NULL;
    203 		if (entry.type == DBUS_TYPE_ARRAY &&
    204 		    entry.array_type == DBUS_TYPE_BYTE) {
    205 			if (entry.array_len <= 0)
    206 				goto error;
    207 
    208 			size = entry.array_len * 2 + 1;
    209 			value = os_zalloc(size);
    210 			if (value == NULL)
    211 				goto error;
    212 
    213 			ret = wpa_snprintf_hex(value, size,
    214 					       (u8 *) entry.bytearray_value,
    215 					       entry.array_len);
    216 			if (ret <= 0)
    217 				goto error;
    218 		} else if (entry.type == DBUS_TYPE_STRING) {
    219 			if (should_quote_opt(entry.key)) {
    220 				size = os_strlen(entry.str_value);
    221 				if (size == 0)
    222 					goto error;
    223 
    224 				size += 3;
    225 				value = os_zalloc(size);
    226 				if (value == NULL)
    227 					goto error;
    228 
    229 				ret = os_snprintf(value, size, "\"%s\"",
    230 						  entry.str_value);
    231 				if (os_snprintf_error(size, ret))
    232 					goto error;
    233 			} else {
    234 				value = os_strdup(entry.str_value);
    235 				if (value == NULL)
    236 					goto error;
    237 			}
    238 		} else if (entry.type == DBUS_TYPE_UINT32) {
    239 			value = os_zalloc(size);
    240 			if (value == NULL)
    241 				goto error;
    242 
    243 			ret = os_snprintf(value, size, "%u",
    244 					  entry.uint32_value);
    245 			if (os_snprintf_error(size, ret))
    246 				goto error;
    247 		} else if (entry.type == DBUS_TYPE_INT32) {
    248 			value = os_zalloc(size);
    249 			if (value == NULL)
    250 				goto error;
    251 
    252 			ret = os_snprintf(value, size, "%d",
    253 					  entry.int32_value);
    254 			if (os_snprintf_error(size, ret))
    255 				goto error;
    256 		} else
    257 			goto error;
    258 
    259 		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
    260 			goto error;
    261 
    262 		if (os_strcmp(entry.key, "bssid") != 0 &&
    263 		    os_strcmp(entry.key, "priority") != 0)
    264 			wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
    265 
    266 		if (wpa_s->current_ssid == ssid ||
    267 		    wpa_s->current_ssid == NULL) {
    268 			/*
    269 			 * Invalidate the EAP session cache if anything in the
    270 			 * current or previously used configuration changes.
    271 			 */
    272 			eapol_sm_invalidate_cached_session(wpa_s->eapol);
    273 		}
    274 
    275 		if ((os_strcmp(entry.key, "psk") == 0 &&
    276 		     value[0] == '"' && ssid->ssid_len) ||
    277 		    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
    278 			wpa_config_update_psk(ssid);
    279 		else if (os_strcmp(entry.key, "priority") == 0)
    280 			wpa_config_update_prio_list(wpa_s->conf);
    281 
    282 		os_free(value);
    283 		value = NULL;
    284 		wpa_dbus_dict_entry_clear(&entry);
    285 	}
    286 
    287 	return TRUE;
    288 
    289 error:
    290 	os_free(value);
    291 	wpa_dbus_dict_entry_clear(&entry);
    292 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    293 			     "invalid message format");
    294 	return FALSE;
    295 }
    296 
    297 
    298 /**
    299  * wpas_dbus_simple_property_getter - Get basic type property
    300  * @iter: Message iter to use when appending arguments
    301  * @type: DBus type of property (must be basic type)
    302  * @val: pointer to place holding property value
    303  * @error: On failure an error describing the failure
    304  * Returns: TRUE if the request was successful, FALSE if it failed
    305  *
    306  * Generic getter for basic type properties. Type is required to be basic.
    307  */
    308 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
    309 					     const int type,
    310 					     const void *val,
    311 					     DBusError *error)
    312 {
    313 	DBusMessageIter variant_iter;
    314 
    315 	if (!dbus_type_is_basic(type)) {
    316 		dbus_set_error(error, DBUS_ERROR_FAILED,
    317 			       "%s: given type is not basic", __func__);
    318 		return FALSE;
    319 	}
    320 
    321 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    322 					      wpa_dbus_type_as_string(type),
    323 					      &variant_iter) ||
    324 	    !dbus_message_iter_append_basic(&variant_iter, type, val) ||
    325 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
    326 		dbus_set_error(error, DBUS_ERROR_FAILED,
    327 			       "%s: error constructing reply", __func__);
    328 		return FALSE;
    329 	}
    330 
    331 	return TRUE;
    332 }
    333 
    334 
    335 /**
    336  * wpas_dbus_simple_property_setter - Set basic type property
    337  * @message: Pointer to incoming dbus message
    338  * @type: DBus type of property (must be basic type)
    339  * @val: pointer to place where value being set will be stored
    340  * Returns: TRUE if the request was successful, FALSE if it failed
    341  *
    342  * Generic setter for basic type properties. Type is required to be basic.
    343  */
    344 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
    345 					     DBusError *error,
    346 					     const int type, void *val)
    347 {
    348 	DBusMessageIter variant_iter;
    349 
    350 	if (!dbus_type_is_basic(type)) {
    351 		dbus_set_error(error, DBUS_ERROR_FAILED,
    352 			       "%s: given type is not basic", __func__);
    353 		return FALSE;
    354 	}
    355 
    356 	/* Look at the new value */
    357 	dbus_message_iter_recurse(iter, &variant_iter);
    358 	if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
    359 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
    360 				     "wrong property type");
    361 		return FALSE;
    362 	}
    363 	dbus_message_iter_get_basic(&variant_iter, val);
    364 
    365 	return TRUE;
    366 }
    367 
    368 
    369 /**
    370  * wpas_dbus_simple_array_property_getter - Get array type property
    371  * @iter: Pointer to incoming dbus message iterator
    372  * @type: DBus type of property array elements (must be basic type)
    373  * @array: pointer to array of elements to put into response message
    374  * @array_len: length of above array
    375  * @error: a pointer to an error to fill on failure
    376  * Returns: TRUE if the request succeeded, FALSE if it failed
    377  *
    378  * Generic getter for array type properties. Array elements type is
    379  * required to be basic.
    380  */
    381 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
    382 						   const int type,
    383 						   const void *array,
    384 						   size_t array_len,
    385 						   DBusError *error)
    386 {
    387 	DBusMessageIter variant_iter, array_iter;
    388 	char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
    389 	const char *sub_type_str;
    390 	size_t element_size, i;
    391 
    392 	if (!dbus_type_is_basic(type)) {
    393 		dbus_set_error(error, DBUS_ERROR_FAILED,
    394 			       "%s: given type is not basic", __func__);
    395 		return FALSE;
    396 	}
    397 
    398 	sub_type_str = wpa_dbus_type_as_string(type);
    399 	type_str[1] = sub_type_str[0];
    400 
    401 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    402 					      type_str, &variant_iter) ||
    403 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
    404 					      sub_type_str, &array_iter)) {
    405 		dbus_set_error(error, DBUS_ERROR_FAILED,
    406 			       "%s: failed to construct message", __func__);
    407 		return FALSE;
    408 	}
    409 
    410 	switch (type) {
    411 	case DBUS_TYPE_BYTE:
    412 	case DBUS_TYPE_BOOLEAN:
    413 		element_size = 1;
    414 		break;
    415 	case DBUS_TYPE_INT16:
    416 	case DBUS_TYPE_UINT16:
    417 		element_size = sizeof(uint16_t);
    418 		break;
    419 	case DBUS_TYPE_INT32:
    420 	case DBUS_TYPE_UINT32:
    421 		element_size = sizeof(uint32_t);
    422 		break;
    423 	case DBUS_TYPE_INT64:
    424 	case DBUS_TYPE_UINT64:
    425 		element_size = sizeof(uint64_t);
    426 		break;
    427 	case DBUS_TYPE_DOUBLE:
    428 		element_size = sizeof(double);
    429 		break;
    430 	case DBUS_TYPE_STRING:
    431 	case DBUS_TYPE_OBJECT_PATH:
    432 		element_size = sizeof(char *);
    433 		break;
    434 	default:
    435 		dbus_set_error(error, DBUS_ERROR_FAILED,
    436 			       "%s: unknown element type %d", __func__, type);
    437 		return FALSE;
    438 	}
    439 
    440 	for (i = 0; i < array_len; i++) {
    441 		if (!dbus_message_iter_append_basic(&array_iter, type,
    442 						    (const char *) array +
    443 						    i * element_size)) {
    444 			dbus_set_error(error, DBUS_ERROR_FAILED,
    445 				       "%s: failed to construct message 2.5",
    446 				       __func__);
    447 			return FALSE;
    448 		}
    449 	}
    450 
    451 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
    452 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
    453 		dbus_set_error(error, DBUS_ERROR_FAILED,
    454 			       "%s: failed to construct message 3", __func__);
    455 		return FALSE;
    456 	}
    457 
    458 	return TRUE;
    459 }
    460 
    461 
    462 /**
    463  * wpas_dbus_simple_array_array_property_getter - Get array array type property
    464  * @iter: Pointer to incoming dbus message iterator
    465  * @type: DBus type of property array elements (must be basic type)
    466  * @array: pointer to array of elements to put into response message
    467  * @array_len: length of above array
    468  * @error: a pointer to an error to fill on failure
    469  * Returns: TRUE if the request succeeded, FALSE if it failed
    470  *
    471  * Generic getter for array type properties. Array elements type is
    472  * required to be basic.
    473  */
    474 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
    475 							 const int type,
    476 							 struct wpabuf **array,
    477 							 size_t array_len,
    478 							 DBusError *error)
    479 {
    480 	DBusMessageIter variant_iter, array_iter;
    481 	char type_str[] = "aa?";
    482 	char inner_type_str[] = "a?";
    483 	const char *sub_type_str;
    484 	size_t i;
    485 
    486 	if (!dbus_type_is_basic(type)) {
    487 		dbus_set_error(error, DBUS_ERROR_FAILED,
    488 			       "%s: given type is not basic", __func__);
    489 		return FALSE;
    490 	}
    491 
    492 	sub_type_str = wpa_dbus_type_as_string(type);
    493 	type_str[2] = sub_type_str[0];
    494 	inner_type_str[1] = sub_type_str[0];
    495 
    496 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    497 					      type_str, &variant_iter) ||
    498 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
    499 					      inner_type_str, &array_iter)) {
    500 		dbus_set_error(error, DBUS_ERROR_FAILED,
    501 			       "%s: failed to construct message", __func__);
    502 		return FALSE;
    503 	}
    504 
    505 	for (i = 0; i < array_len && array[i]; i++) {
    506 		wpa_dbus_dict_bin_array_add_element(&array_iter,
    507 						    wpabuf_head(array[i]),
    508 						    wpabuf_len(array[i]));
    509 
    510 	}
    511 
    512 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
    513 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
    514 		dbus_set_error(error, DBUS_ERROR_FAILED,
    515 			       "%s: failed to close message", __func__);
    516 		return FALSE;
    517 	}
    518 
    519 	return TRUE;
    520 }
    521 
    522 
    523 /**
    524  * wpas_dbus_string_property_getter - Get string type property
    525  * @iter: Message iter to use when appending arguments
    526  * @val: Pointer to place holding property value, can be %NULL
    527  * @error: On failure an error describing the failure
    528  * Returns: TRUE if the request was successful, FALSE if it failed
    529  *
    530  * Generic getter for string type properties. %NULL is converted to an empty
    531  * string.
    532  */
    533 dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
    534 					     const void *val,
    535 					     DBusError *error)
    536 {
    537 	if (!val)
    538 		val = "";
    539 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    540 						&val, error);
    541 }
    542 
    543 
    544 /**
    545  * wpas_dbus_handler_create_interface - Request registration of a network iface
    546  * @message: Pointer to incoming dbus message
    547  * @global: %wpa_supplicant global data structure
    548  * Returns: The object path of the new interface object,
    549  *          or a dbus error message with more information
    550  *
    551  * Handler function for "CreateInterface" method call. Handles requests
    552  * by dbus clients to register a network interface that wpa_supplicant
    553  * will manage.
    554  */
    555 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
    556 						 struct wpa_global *global)
    557 {
    558 	DBusMessageIter iter_dict;
    559 	DBusMessage *reply = NULL;
    560 	DBusMessageIter iter;
    561 	struct wpa_dbus_dict_entry entry;
    562 	char *driver = NULL;
    563 	char *ifname = NULL;
    564 	char *confname = NULL;
    565 	char *bridge_ifname = NULL;
    566 
    567 	dbus_message_iter_init(message, &iter);
    568 
    569 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    570 		goto error;
    571 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    572 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    573 			goto error;
    574 		if (os_strcmp(entry.key, "Driver") == 0 &&
    575 		    entry.type == DBUS_TYPE_STRING) {
    576 			os_free(driver);
    577 			driver = os_strdup(entry.str_value);
    578 			wpa_dbus_dict_entry_clear(&entry);
    579 			if (driver == NULL)
    580 				goto oom;
    581 		} else if (os_strcmp(entry.key, "Ifname") == 0 &&
    582 			   entry.type == DBUS_TYPE_STRING) {
    583 			os_free(ifname);
    584 			ifname = os_strdup(entry.str_value);
    585 			wpa_dbus_dict_entry_clear(&entry);
    586 			if (ifname == NULL)
    587 				goto oom;
    588 		} else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
    589 			   entry.type == DBUS_TYPE_STRING) {
    590 			os_free(confname);
    591 			confname = os_strdup(entry.str_value);
    592 			wpa_dbus_dict_entry_clear(&entry);
    593 			if (confname == NULL)
    594 				goto oom;
    595 		} else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
    596 			   entry.type == DBUS_TYPE_STRING) {
    597 			os_free(bridge_ifname);
    598 			bridge_ifname = os_strdup(entry.str_value);
    599 			wpa_dbus_dict_entry_clear(&entry);
    600 			if (bridge_ifname == NULL)
    601 				goto oom;
    602 		} else {
    603 			wpa_dbus_dict_entry_clear(&entry);
    604 			goto error;
    605 		}
    606 	}
    607 
    608 	if (ifname == NULL)
    609 		goto error; /* Required Ifname argument missing */
    610 
    611 	/*
    612 	 * Try to get the wpa_supplicant record for this iface, return
    613 	 * an error if we already control it.
    614 	 */
    615 	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
    616 		reply = dbus_message_new_error(
    617 			message, WPAS_DBUS_ERROR_IFACE_EXISTS,
    618 			"wpa_supplicant already controls this interface.");
    619 	} else {
    620 		struct wpa_supplicant *wpa_s;
    621 		struct wpa_interface iface;
    622 
    623 		os_memset(&iface, 0, sizeof(iface));
    624 		iface.driver = driver;
    625 		iface.ifname = ifname;
    626 		iface.confname = confname;
    627 		iface.bridge_ifname = bridge_ifname;
    628 		/* Otherwise, have wpa_supplicant attach to it. */
    629 		wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
    630 		if (wpa_s && wpa_s->dbus_new_path) {
    631 			const char *path = wpa_s->dbus_new_path;
    632 
    633 			reply = dbus_message_new_method_return(message);
    634 			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
    635 						 &path, DBUS_TYPE_INVALID);
    636 		} else {
    637 			reply = wpas_dbus_error_unknown_error(
    638 				message,
    639 				"wpa_supplicant couldn't grab this interface.");
    640 		}
    641 	}
    642 
    643 out:
    644 	os_free(driver);
    645 	os_free(ifname);
    646 	os_free(confname);
    647 	os_free(bridge_ifname);
    648 	return reply;
    649 
    650 error:
    651 	reply = wpas_dbus_error_invalid_args(message, NULL);
    652 	goto out;
    653 oom:
    654 	reply = wpas_dbus_error_no_memory(message);
    655 	goto out;
    656 }
    657 
    658 
    659 /**
    660  * wpas_dbus_handler_remove_interface - Request deregistration of an interface
    661  * @message: Pointer to incoming dbus message
    662  * @global: wpa_supplicant global data structure
    663  * Returns: a dbus message containing a UINT32 indicating success (1) or
    664  *          failure (0), or returns a dbus error message with more information
    665  *
    666  * Handler function for "removeInterface" method call.  Handles requests
    667  * by dbus clients to deregister a network interface that wpa_supplicant
    668  * currently manages.
    669  */
    670 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
    671 						 struct wpa_global *global)
    672 {
    673 	struct wpa_supplicant *wpa_s;
    674 	char *path;
    675 	DBusMessage *reply = NULL;
    676 
    677 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
    678 			      DBUS_TYPE_INVALID);
    679 
    680 	wpa_s = get_iface_by_dbus_path(global, path);
    681 	if (wpa_s == NULL)
    682 		reply = wpas_dbus_error_iface_unknown(message);
    683 	else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) {
    684 		reply = wpas_dbus_error_unknown_error(
    685 			message,
    686 			"wpa_supplicant couldn't remove this interface.");
    687 	}
    688 
    689 	return reply;
    690 }
    691 
    692 
    693 /**
    694  * wpas_dbus_handler_get_interface - Get the object path for an interface name
    695  * @message: Pointer to incoming dbus message
    696  * @global: %wpa_supplicant global data structure
    697  * Returns: The object path of the interface object,
    698  *          or a dbus error message with more information
    699  *
    700  * Handler function for "getInterface" method call.
    701  */
    702 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
    703 					      struct wpa_global *global)
    704 {
    705 	DBusMessage *reply = NULL;
    706 	const char *ifname;
    707 	const char *path;
    708 	struct wpa_supplicant *wpa_s;
    709 
    710 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
    711 			      DBUS_TYPE_INVALID);
    712 
    713 	wpa_s = wpa_supplicant_get_iface(global, ifname);
    714 	if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
    715 		return wpas_dbus_error_iface_unknown(message);
    716 
    717 	path = wpa_s->dbus_new_path;
    718 	reply = dbus_message_new_method_return(message);
    719 	if (reply == NULL)
    720 		return wpas_dbus_error_no_memory(message);
    721 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
    722 				      DBUS_TYPE_INVALID)) {
    723 		dbus_message_unref(reply);
    724 		return wpas_dbus_error_no_memory(message);
    725 	}
    726 
    727 	return reply;
    728 }
    729 
    730 
    731 /**
    732  * wpas_dbus_getter_debug_level - Get debug level
    733  * @iter: Pointer to incoming dbus message iter
    734  * @error: Location to store error on failure
    735  * @user_data: Function specific data
    736  * Returns: TRUE on success, FALSE on failure
    737  *
    738  * Getter for "DebugLevel" property.
    739  */
    740 dbus_bool_t wpas_dbus_getter_debug_level(
    741 	const struct wpa_dbus_property_desc *property_desc,
    742 	DBusMessageIter *iter, DBusError *error, void *user_data)
    743 {
    744 	const char *str;
    745 	int idx = wpa_debug_level;
    746 
    747 	if (idx < 0)
    748 		idx = 0;
    749 	if (idx > 5)
    750 		idx = 5;
    751 	str = debug_strings[idx];
    752 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
    753 						&str, error);
    754 }
    755 
    756 
    757 /**
    758  * wpas_dbus_getter_debug_timestamp - Get debug timestamp
    759  * @iter: Pointer to incoming dbus message iter
    760  * @error: Location to store error on failure
    761  * @user_data: Function specific data
    762  * Returns: TRUE on success, FALSE on failure
    763  *
    764  * Getter for "DebugTimestamp" property.
    765  */
    766 dbus_bool_t wpas_dbus_getter_debug_timestamp(
    767 	const struct wpa_dbus_property_desc *property_desc,
    768 	DBusMessageIter *iter, DBusError *error, void *user_data)
    769 {
    770 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    771 						&wpa_debug_timestamp, error);
    772 
    773 }
    774 
    775 
    776 /**
    777  * wpas_dbus_getter_debug_show_keys - Get debug show keys
    778  * @iter: Pointer to incoming dbus message iter
    779  * @error: Location to store error on failure
    780  * @user_data: Function specific data
    781  * Returns: TRUE on success, FALSE on failure
    782  *
    783  * Getter for "DebugShowKeys" property.
    784  */
    785 dbus_bool_t wpas_dbus_getter_debug_show_keys(
    786 	const struct wpa_dbus_property_desc *property_desc,
    787 	DBusMessageIter *iter, DBusError *error, void *user_data)
    788 {
    789 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
    790 						&wpa_debug_show_keys, error);
    791 
    792 }
    793 
    794 /**
    795  * wpas_dbus_setter_debug_level - Set debug level
    796  * @iter: Pointer to incoming dbus message iter
    797  * @error: Location to store error on failure
    798  * @user_data: Function specific data
    799  * Returns: TRUE on success, FALSE on failure
    800  *
    801  * Setter for "DebugLevel" property.
    802  */
    803 dbus_bool_t wpas_dbus_setter_debug_level(
    804 	const struct wpa_dbus_property_desc *property_desc,
    805 	DBusMessageIter *iter, DBusError *error, void *user_data)
    806 {
    807 	struct wpa_global *global = user_data;
    808 	const char *str = NULL;
    809 	int i, val = -1;
    810 
    811 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
    812 					      &str))
    813 		return FALSE;
    814 
    815 	for (i = 0; debug_strings[i]; i++)
    816 		if (os_strcmp(debug_strings[i], str) == 0) {
    817 			val = i;
    818 			break;
    819 		}
    820 
    821 	if (val < 0 ||
    822 	    wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
    823 					    wpa_debug_show_keys)) {
    824 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
    825 				     "wrong debug level value");
    826 		return FALSE;
    827 	}
    828 
    829 	return TRUE;
    830 }
    831 
    832 
    833 /**
    834  * wpas_dbus_setter_debug_timestamp - Set debug timestamp
    835  * @iter: Pointer to incoming dbus message iter
    836  * @error: Location to store error on failure
    837  * @user_data: Function specific data
    838  * Returns: TRUE on success, FALSE on failure
    839  *
    840  * Setter for "DebugTimestamp" property.
    841  */
    842 dbus_bool_t wpas_dbus_setter_debug_timestamp(
    843 	const struct wpa_dbus_property_desc *property_desc,
    844 	DBusMessageIter *iter, DBusError *error, void *user_data)
    845 {
    846 	struct wpa_global *global = user_data;
    847 	dbus_bool_t val;
    848 
    849 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
    850 					      &val))
    851 		return FALSE;
    852 
    853 	wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
    854 					wpa_debug_show_keys);
    855 	return TRUE;
    856 }
    857 
    858 
    859 /**
    860  * wpas_dbus_setter_debug_show_keys - Set debug show keys
    861  * @iter: Pointer to incoming dbus message iter
    862  * @error: Location to store error on failure
    863  * @user_data: Function specific data
    864  * Returns: TRUE on success, FALSE on failure
    865  *
    866  * Setter for "DebugShowKeys" property.
    867  */
    868 dbus_bool_t wpas_dbus_setter_debug_show_keys(
    869 	const struct wpa_dbus_property_desc *property_desc,
    870 	DBusMessageIter *iter, DBusError *error, void *user_data)
    871 {
    872 	struct wpa_global *global = user_data;
    873 	dbus_bool_t val;
    874 
    875 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
    876 					      &val))
    877 		return FALSE;
    878 
    879 	wpa_supplicant_set_debug_params(global, wpa_debug_level,
    880 					wpa_debug_timestamp,
    881 					val ? 1 : 0);
    882 	return TRUE;
    883 }
    884 
    885 
    886 /**
    887  * wpas_dbus_getter_interfaces - Request registered interfaces list
    888  * @iter: Pointer to incoming dbus message iter
    889  * @error: Location to store error on failure
    890  * @user_data: Function specific data
    891  * Returns: TRUE on success, FALSE on failure
    892  *
    893  * Getter for "Interfaces" property. Handles requests
    894  * by dbus clients to return list of registered interfaces objects
    895  * paths
    896  */
    897 dbus_bool_t wpas_dbus_getter_interfaces(
    898 	const struct wpa_dbus_property_desc *property_desc,
    899 	DBusMessageIter *iter, DBusError *error, void *user_data)
    900 {
    901 	struct wpa_global *global = user_data;
    902 	struct wpa_supplicant *wpa_s;
    903 	const char **paths;
    904 	unsigned int i = 0, num = 0;
    905 	dbus_bool_t success;
    906 
    907 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    908 		if (wpa_s->dbus_new_path)
    909 			num++;
    910 	}
    911 
    912 	paths = os_calloc(num, sizeof(char *));
    913 	if (!paths) {
    914 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    915 		return FALSE;
    916 	}
    917 
    918 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
    919 		if (wpa_s->dbus_new_path)
    920 			paths[i++] = wpa_s->dbus_new_path;
    921 	}
    922 
    923 	success = wpas_dbus_simple_array_property_getter(iter,
    924 							 DBUS_TYPE_OBJECT_PATH,
    925 							 paths, num, error);
    926 
    927 	os_free(paths);
    928 	return success;
    929 }
    930 
    931 
    932 /**
    933  * wpas_dbus_getter_eap_methods - Request supported EAP methods list
    934  * @iter: Pointer to incoming dbus message iter
    935  * @error: Location to store error on failure
    936  * @user_data: Function specific data
    937  * Returns: TRUE on success, FALSE on failure
    938  *
    939  * Getter for "EapMethods" property. Handles requests
    940  * by dbus clients to return list of strings with supported EAP methods
    941  */
    942 dbus_bool_t wpas_dbus_getter_eap_methods(
    943 	const struct wpa_dbus_property_desc *property_desc,
    944 	DBusMessageIter *iter, DBusError *error, void *user_data)
    945 {
    946 	char **eap_methods;
    947 	size_t num_items = 0;
    948 	dbus_bool_t success;
    949 
    950 	eap_methods = eap_get_names_as_string_array(&num_items);
    951 	if (!eap_methods) {
    952 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    953 		return FALSE;
    954 	}
    955 
    956 	success = wpas_dbus_simple_array_property_getter(iter,
    957 							 DBUS_TYPE_STRING,
    958 							 eap_methods,
    959 							 num_items, error);
    960 
    961 	while (num_items)
    962 		os_free(eap_methods[--num_items]);
    963 	os_free(eap_methods);
    964 	return success;
    965 }
    966 
    967 
    968 /**
    969  * wpas_dbus_getter_global_capabilities - Request supported global capabilities
    970  * @iter: Pointer to incoming dbus message iter
    971  * @error: Location to store error on failure
    972  * @user_data: Function specific data
    973  * Returns: TRUE on success, FALSE on failure
    974  *
    975  * Getter for "Capabilities" property. Handles requests by dbus clients to
    976  * return a list of strings with supported capabilities like AP, RSN IBSS,
    977  * and P2P that are determined at compile time.
    978  */
    979 dbus_bool_t wpas_dbus_getter_global_capabilities(
    980 	const struct wpa_dbus_property_desc *property_desc,
    981 	DBusMessageIter *iter, DBusError *error, void *user_data)
    982 {
    983 	const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
    984 	size_t num_items = 0;
    985 
    986 #ifdef CONFIG_AP
    987 	capabilities[num_items++] = "ap";
    988 #endif /* CONFIG_AP */
    989 #ifdef CONFIG_IBSS_RSN
    990 	capabilities[num_items++] = "ibss-rsn";
    991 #endif /* CONFIG_IBSS_RSN */
    992 #ifdef CONFIG_P2P
    993 	capabilities[num_items++] = "p2p";
    994 #endif /* CONFIG_P2P */
    995 #ifdef CONFIG_INTERWORKING
    996 	capabilities[num_items++] = "interworking";
    997 #endif /* CONFIG_INTERWORKING */
    998 #ifdef CONFIG_IEEE80211W
    999 	capabilities[num_items++] = "pmf";
   1000 #endif /* CONFIG_IEEE80211W */
   1001 
   1002 	return wpas_dbus_simple_array_property_getter(iter,
   1003 						      DBUS_TYPE_STRING,
   1004 						      capabilities,
   1005 						      num_items, error);
   1006 }
   1007 
   1008 
   1009 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
   1010 				   char **type, DBusMessage **reply)
   1011 {
   1012 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
   1013 		wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string",
   1014 			   __func__);
   1015 		*reply = wpas_dbus_error_invalid_args(
   1016 			message, "Wrong Type value type. String required");
   1017 		return -1;
   1018 	}
   1019 	dbus_message_iter_get_basic(var, type);
   1020 	return 0;
   1021 }
   1022 
   1023 
   1024 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
   1025 				    struct wpa_driver_scan_params *params,
   1026 				    DBusMessage **reply)
   1027 {
   1028 	struct wpa_driver_scan_ssid *ssids = params->ssids;
   1029 	size_t ssids_num = 0;
   1030 	u8 *ssid;
   1031 	DBusMessageIter array_iter, sub_array_iter;
   1032 	char *val;
   1033 	int len;
   1034 
   1035 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
   1036 		wpa_printf(MSG_DEBUG,
   1037 			   "%s[dbus]: ssids must be an array of arrays of bytes",
   1038 			   __func__);
   1039 		*reply = wpas_dbus_error_invalid_args(
   1040 			message,
   1041 			"Wrong SSIDs value type. Array of arrays of bytes required");
   1042 		return -1;
   1043 	}
   1044 
   1045 	dbus_message_iter_recurse(var, &array_iter);
   1046 
   1047 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
   1048 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
   1049 		wpa_printf(MSG_DEBUG,
   1050 			   "%s[dbus]: ssids must be an array of arrays of bytes",
   1051 			   __func__);
   1052 		*reply = wpas_dbus_error_invalid_args(
   1053 			message,
   1054 			"Wrong SSIDs value type. Array of arrays of bytes required");
   1055 		return -1;
   1056 	}
   1057 
   1058 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
   1059 		if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
   1060 			wpa_printf(MSG_DEBUG,
   1061 				   "%s[dbus]: Too many ssids specified on scan dbus call",
   1062 				   __func__);
   1063 			*reply = wpas_dbus_error_invalid_args(
   1064 				message,
   1065 				"Too many ssids specified. Specify at most four");
   1066 			return -1;
   1067 		}
   1068 
   1069 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
   1070 
   1071 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
   1072 
   1073 		if (len > SSID_MAX_LEN) {
   1074 			wpa_printf(MSG_DEBUG,
   1075 				   "%s[dbus]: SSID too long (len=%d max_len=%d)",
   1076 				   __func__, len, SSID_MAX_LEN);
   1077 			*reply = wpas_dbus_error_invalid_args(
   1078 				message, "Invalid SSID: too long");
   1079 			return -1;
   1080 		}
   1081 
   1082 		if (len != 0) {
   1083 			ssid = os_memdup(val, len);
   1084 			if (ssid == NULL) {
   1085 				*reply = wpas_dbus_error_no_memory(message);
   1086 				return -1;
   1087 			}
   1088 		} else {
   1089 			/* Allow zero-length SSIDs */
   1090 			ssid = NULL;
   1091 		}
   1092 
   1093 		ssids[ssids_num].ssid = ssid;
   1094 		ssids[ssids_num].ssid_len = len;
   1095 
   1096 		dbus_message_iter_next(&array_iter);
   1097 		ssids_num++;
   1098 	}
   1099 
   1100 	params->num_ssids = ssids_num;
   1101 	return 0;
   1102 }
   1103 
   1104 
   1105 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
   1106 				  struct wpa_driver_scan_params *params,
   1107 				  DBusMessage **reply)
   1108 {
   1109 	u8 *ies = NULL, *nies;
   1110 	int ies_len = 0;
   1111 	DBusMessageIter array_iter, sub_array_iter;
   1112 	char *val;
   1113 	int len;
   1114 
   1115 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
   1116 		wpa_printf(MSG_DEBUG,
   1117 			   "%s[dbus]: ies must be an array of arrays of bytes",
   1118 			   __func__);
   1119 		*reply = wpas_dbus_error_invalid_args(
   1120 			message,
   1121 			"Wrong IEs value type. Array of arrays of bytes required");
   1122 		return -1;
   1123 	}
   1124 
   1125 	dbus_message_iter_recurse(var, &array_iter);
   1126 
   1127 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
   1128 	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) {
   1129 		wpa_printf(MSG_DEBUG,
   1130 			   "%s[dbus]: ies must be an array of arrays of bytes",
   1131 			   __func__);
   1132 		*reply = wpas_dbus_error_invalid_args(
   1133 			message, "Wrong IEs value type. Array required");
   1134 		return -1;
   1135 	}
   1136 
   1137 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) {
   1138 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
   1139 
   1140 		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
   1141 		if (len == 0) {
   1142 			dbus_message_iter_next(&array_iter);
   1143 			continue;
   1144 		}
   1145 
   1146 		nies = os_realloc(ies, ies_len + len);
   1147 		if (nies == NULL) {
   1148 			os_free(ies);
   1149 			*reply = wpas_dbus_error_no_memory(message);
   1150 			return -1;
   1151 		}
   1152 		ies = nies;
   1153 		os_memcpy(ies + ies_len, val, len);
   1154 		ies_len += len;
   1155 
   1156 		dbus_message_iter_next(&array_iter);
   1157 	}
   1158 
   1159 	params->extra_ies = ies;
   1160 	params->extra_ies_len = ies_len;
   1161 	return 0;
   1162 }
   1163 
   1164 
   1165 static int wpas_dbus_get_scan_channels(DBusMessage *message,
   1166 				       DBusMessageIter *var,
   1167 				       struct wpa_driver_scan_params *params,
   1168 				       DBusMessage **reply)
   1169 {
   1170 	DBusMessageIter array_iter, sub_array_iter;
   1171 	int *freqs = NULL, *nfreqs;
   1172 	int freqs_num = 0;
   1173 
   1174 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
   1175 		wpa_printf(MSG_DEBUG,
   1176 			   "%s[dbus]: Channels must be an array of structs",
   1177 			   __func__);
   1178 		*reply = wpas_dbus_error_invalid_args(
   1179 			message,
   1180 			"Wrong Channels value type. Array of structs required");
   1181 		return -1;
   1182 	}
   1183 
   1184 	dbus_message_iter_recurse(var, &array_iter);
   1185 
   1186 	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
   1187 		wpa_printf(MSG_DEBUG,
   1188 			   "%s[dbus]: Channels must be an array of structs",
   1189 			   __func__);
   1190 		*reply = wpas_dbus_error_invalid_args(
   1191 			message,
   1192 			"Wrong Channels value type. Array of structs required");
   1193 		return -1;
   1194 	}
   1195 
   1196 	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
   1197 	{
   1198 		int freq, width;
   1199 
   1200 		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
   1201 
   1202 		if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
   1203 		    DBUS_TYPE_UINT32) {
   1204 			wpa_printf(MSG_DEBUG,
   1205 				   "%s[dbus]: Channel must by specified by struct of two UINT32s %c",
   1206 				   __func__,
   1207 				   dbus_message_iter_get_arg_type(
   1208 					   &sub_array_iter));
   1209 			*reply = wpas_dbus_error_invalid_args(
   1210 				message,
   1211 				"Wrong Channel struct. Two UINT32s required");
   1212 			os_free(freqs);
   1213 			return -1;
   1214 		}
   1215 		dbus_message_iter_get_basic(&sub_array_iter, &freq);
   1216 
   1217 		if (!dbus_message_iter_next(&sub_array_iter) ||
   1218 		    dbus_message_iter_get_arg_type(&sub_array_iter) !=
   1219 		    DBUS_TYPE_UINT32) {
   1220 			wpa_printf(MSG_DEBUG,
   1221 				   "%s[dbus]: Channel must by specified by struct of two UINT32s",
   1222 				   __func__);
   1223 			*reply = wpas_dbus_error_invalid_args(
   1224 				message,
   1225 				"Wrong Channel struct. Two UINT32s required");
   1226 			os_free(freqs);
   1227 			return -1;
   1228 		}
   1229 
   1230 		dbus_message_iter_get_basic(&sub_array_iter, &width);
   1231 
   1232 #define FREQS_ALLOC_CHUNK 32
   1233 		if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
   1234 			nfreqs = os_realloc_array(
   1235 				freqs, freqs_num + FREQS_ALLOC_CHUNK,
   1236 				sizeof(int));
   1237 			if (nfreqs == NULL)
   1238 				os_free(freqs);
   1239 			freqs = nfreqs;
   1240 		}
   1241 		if (freqs == NULL) {
   1242 			*reply = wpas_dbus_error_no_memory(message);
   1243 			return -1;
   1244 		}
   1245 
   1246 		freqs[freqs_num] = freq;
   1247 
   1248 		freqs_num++;
   1249 		dbus_message_iter_next(&array_iter);
   1250 	}
   1251 
   1252 	nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int));
   1253 	if (nfreqs == NULL)
   1254 		os_free(freqs);
   1255 	freqs = nfreqs;
   1256 	if (freqs == NULL) {
   1257 		*reply = wpas_dbus_error_no_memory(message);
   1258 		return -1;
   1259 	}
   1260 	freqs[freqs_num] = 0;
   1261 
   1262 	params->freqs = freqs;
   1263 	return 0;
   1264 }
   1265 
   1266 
   1267 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message,
   1268 					 DBusMessageIter *var,
   1269 					 dbus_bool_t *allow,
   1270 					 DBusMessage **reply)
   1271 {
   1272 	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) {
   1273 		wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean",
   1274 			   __func__);
   1275 		*reply = wpas_dbus_error_invalid_args(
   1276 			message, "Wrong Type value type. Boolean required");
   1277 		return -1;
   1278 	}
   1279 	dbus_message_iter_get_basic(var, allow);
   1280 	return 0;
   1281 }
   1282 
   1283 
   1284 /**
   1285  * wpas_dbus_handler_scan - Request a wireless scan on an interface
   1286  * @message: Pointer to incoming dbus message
   1287  * @wpa_s: wpa_supplicant structure for a network interface
   1288  * Returns: NULL indicating success or DBus error message on failure
   1289  *
   1290  * Handler function for "Scan" method call of a network device. Requests
   1291  * that wpa_supplicant perform a wireless scan as soon as possible
   1292  * on a particular wireless interface.
   1293  */
   1294 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
   1295 				     struct wpa_supplicant *wpa_s)
   1296 {
   1297 	DBusMessage *reply = NULL;
   1298 	DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
   1299 	char *key = NULL, *type = NULL;
   1300 	struct wpa_driver_scan_params params;
   1301 	size_t i;
   1302 	dbus_bool_t allow_roam = 1;
   1303 
   1304 	os_memset(&params, 0, sizeof(params));
   1305 
   1306 	dbus_message_iter_init(message, &iter);
   1307 
   1308 	dbus_message_iter_recurse(&iter, &dict_iter);
   1309 
   1310 	while (dbus_message_iter_get_arg_type(&dict_iter) ==
   1311 	       DBUS_TYPE_DICT_ENTRY) {
   1312 		dbus_message_iter_recurse(&dict_iter, &entry_iter);
   1313 		dbus_message_iter_get_basic(&entry_iter, &key);
   1314 		dbus_message_iter_next(&entry_iter);
   1315 		dbus_message_iter_recurse(&entry_iter, &variant_iter);
   1316 
   1317 		if (os_strcmp(key, "Type") == 0) {
   1318 			if (wpas_dbus_get_scan_type(message, &variant_iter,
   1319 						    &type, &reply) < 0)
   1320 				goto out;
   1321 		} else if (os_strcmp(key, "SSIDs") == 0) {
   1322 			if (wpas_dbus_get_scan_ssids(message, &variant_iter,
   1323 						     &params, &reply) < 0)
   1324 				goto out;
   1325 		} else if (os_strcmp(key, "IEs") == 0) {
   1326 			if (wpas_dbus_get_scan_ies(message, &variant_iter,
   1327 						   &params, &reply) < 0)
   1328 				goto out;
   1329 		} else if (os_strcmp(key, "Channels") == 0) {
   1330 			if (wpas_dbus_get_scan_channels(message, &variant_iter,
   1331 							&params, &reply) < 0)
   1332 				goto out;
   1333 		} else if (os_strcmp(key, "AllowRoam") == 0) {
   1334 			if (wpas_dbus_get_scan_allow_roam(message,
   1335 							  &variant_iter,
   1336 							  &allow_roam,
   1337 							  &reply) < 0)
   1338 				goto out;
   1339 		} else {
   1340 			wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s",
   1341 				   __func__, key);
   1342 			reply = wpas_dbus_error_invalid_args(message, key);
   1343 			goto out;
   1344 		}
   1345 
   1346 		dbus_message_iter_next(&dict_iter);
   1347 	}
   1348 
   1349 	if (!type) {
   1350 		wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified",
   1351 			   __func__);
   1352 		reply = wpas_dbus_error_invalid_args(message, key);
   1353 		goto out;
   1354 	}
   1355 
   1356 	if (os_strcmp(type, "passive") == 0) {
   1357 		if (params.num_ssids || params.extra_ies_len) {
   1358 			wpa_printf(MSG_DEBUG,
   1359 				   "%s[dbus]: SSIDs or IEs specified for passive scan.",
   1360 				   __func__);
   1361 			reply = wpas_dbus_error_invalid_args(
   1362 				message,
   1363 				"You can specify only Channels in passive scan");
   1364 			goto out;
   1365 		} else {
   1366 			if (wpa_s->sched_scanning) {
   1367 				wpa_printf(MSG_DEBUG,
   1368 					   "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
   1369 					   __func__);
   1370 				wpa_supplicant_cancel_sched_scan(wpa_s);
   1371 			}
   1372 
   1373 			if (params.freqs && params.freqs[0]) {
   1374 				wpa_s->last_scan_req = MANUAL_SCAN_REQ;
   1375 				if (wpa_supplicant_trigger_scan(wpa_s,
   1376 								&params)) {
   1377 					reply = wpas_dbus_error_scan_error(
   1378 						message,
   1379 						"Scan request rejected");
   1380 				}
   1381 			} else {
   1382 				wpa_s->scan_req = MANUAL_SCAN_REQ;
   1383 				wpa_supplicant_req_scan(wpa_s, 0, 0);
   1384 			}
   1385 		}
   1386 	} else if (os_strcmp(type, "active") == 0) {
   1387 		if (!params.num_ssids) {
   1388 			/* Add wildcard ssid */
   1389 			params.num_ssids++;
   1390 		}
   1391 #ifdef CONFIG_AUTOSCAN
   1392 		autoscan_deinit(wpa_s);
   1393 #endif /* CONFIG_AUTOSCAN */
   1394 		if (wpa_s->sched_scanning) {
   1395 			wpa_printf(MSG_DEBUG,
   1396 				   "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
   1397 				   __func__);
   1398 			wpa_supplicant_cancel_sched_scan(wpa_s);
   1399 		}
   1400 
   1401 		wpa_s->last_scan_req = MANUAL_SCAN_REQ;
   1402 		if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
   1403 			reply = wpas_dbus_error_scan_error(
   1404 				message, "Scan request rejected");
   1405 		}
   1406 	} else {
   1407 		wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s",
   1408 			   __func__, type);
   1409 		reply = wpas_dbus_error_invalid_args(message,
   1410 						     "Wrong scan type");
   1411 		goto out;
   1412 	}
   1413 
   1414 	if (!allow_roam)
   1415 		wpa_s->scan_res_handler = scan_only_handler;
   1416 
   1417 out:
   1418 	for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
   1419 		os_free((u8 *) params.ssids[i].ssid);
   1420 	os_free((u8 *) params.extra_ies);
   1421 	os_free(params.freqs);
   1422 	return reply;
   1423 }
   1424 
   1425 
   1426 /*
   1427  * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted
   1428  * @message: Pointer to incoming dbus message
   1429  * @wpa_s: wpa_supplicant structure for a network interface
   1430  * Returns: Abort failed or no scan in progress DBus error message on failure
   1431  * or NULL otherwise.
   1432  *
   1433  * Handler function for "AbortScan" method call of network interface.
   1434  */
   1435 DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
   1436 					   struct wpa_supplicant *wpa_s)
   1437 {
   1438 	if (wpas_abort_ongoing_scan(wpa_s) < 0)
   1439 		return dbus_message_new_error(
   1440 			message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR,
   1441 			"Abort failed or no scan in progress");
   1442 
   1443 	return NULL;
   1444 }
   1445 
   1446 
   1447 /**
   1448  * wpas_dbus_handler_signal_poll - Request immediate signal properties
   1449  * @message: Pointer to incoming dbus message
   1450  * @wpa_s: wpa_supplicant structure for a network interface
   1451  * Returns: NULL indicating success or DBus error message on failure
   1452  *
   1453  * Handler function for "SignalPoll" method call of a network device. Requests
   1454  * that wpa_supplicant read signal properties like RSSI, noise, and link
   1455  * speed and return them.
   1456  */
   1457 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
   1458 					    struct wpa_supplicant *wpa_s)
   1459 {
   1460 	struct wpa_signal_info si;
   1461 	DBusMessage *reply = NULL;
   1462 	DBusMessageIter iter, iter_dict, variant_iter;
   1463 	int ret;
   1464 
   1465 	ret = wpa_drv_signal_poll(wpa_s, &si);
   1466 	if (ret) {
   1467 		return dbus_message_new_error(message, DBUS_ERROR_FAILED,
   1468 					      "Failed to read signal");
   1469 	}
   1470 
   1471 	reply = dbus_message_new_method_return(message);
   1472 	if (reply == NULL)
   1473 		goto nomem;
   1474 
   1475 	dbus_message_iter_init_append(reply, &iter);
   1476 
   1477 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
   1478 					      "a{sv}", &variant_iter) ||
   1479 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) ||
   1480 	    !wpa_dbus_dict_append_int32(&iter_dict, "rssi",
   1481 					si.current_signal) ||
   1482 	    !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed",
   1483 					si.current_txrate / 1000) ||
   1484 	    !wpa_dbus_dict_append_int32(&iter_dict, "noise",
   1485 					si.current_noise) ||
   1486 	    !wpa_dbus_dict_append_uint32(&iter_dict, "frequency",
   1487 					 si.frequency) ||
   1488 	    (si.chanwidth != CHAN_WIDTH_UNKNOWN &&
   1489 	     !wpa_dbus_dict_append_string(
   1490 		     &iter_dict, "width",
   1491 		     channel_width_to_string(si.chanwidth))) ||
   1492 	    (si.center_frq1 > 0 && si.center_frq2 > 0 &&
   1493 	     (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1",
   1494 					  si.center_frq1) ||
   1495 	      !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2",
   1496 					  si.center_frq2))) ||
   1497 	    (si.avg_signal &&
   1498 	     !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi",
   1499 					 si.avg_signal)) ||
   1500 	    !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
   1501 	    !dbus_message_iter_close_container(&iter, &variant_iter))
   1502 		goto nomem;
   1503 
   1504 	return reply;
   1505 
   1506 nomem:
   1507 	if (reply)
   1508 		dbus_message_unref(reply);
   1509 	return wpas_dbus_error_no_memory(message);
   1510 }
   1511 
   1512 
   1513 /*
   1514  * wpas_dbus_handler_disconnect - Terminate the current connection
   1515  * @message: Pointer to incoming dbus message
   1516  * @wpa_s: wpa_supplicant structure for a network interface
   1517  * Returns: NotConnected DBus error message if already not connected
   1518  * or NULL otherwise.
   1519  *
   1520  * Handler function for "Disconnect" method call of network interface.
   1521  */
   1522 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
   1523 					   struct wpa_supplicant *wpa_s)
   1524 {
   1525 	if (wpa_s->current_ssid != NULL) {
   1526 		wpas_request_disconnection(wpa_s);
   1527 		return NULL;
   1528 	}
   1529 
   1530 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
   1531 				      "This interface is not connected");
   1532 }
   1533 
   1534 
   1535 /**
   1536  * wpas_dbus_new_iface_add_network - Add a new configured network
   1537  * @message: Pointer to incoming dbus message
   1538  * @wpa_s: wpa_supplicant structure for a network interface
   1539  * Returns: A dbus message containing the object path of the new network
   1540  *
   1541  * Handler function for "AddNetwork" method call of a network interface.
   1542  */
   1543 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
   1544 					    struct wpa_supplicant *wpa_s)
   1545 {
   1546 	DBusMessage *reply = NULL;
   1547 	DBusMessageIter	iter;
   1548 	struct wpa_ssid *ssid = NULL;
   1549 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
   1550 	DBusError error;
   1551 
   1552 	dbus_message_iter_init(message, &iter);
   1553 
   1554 	if (wpa_s->dbus_new_path)
   1555 		ssid = wpa_supplicant_add_network(wpa_s);
   1556 	if (ssid == NULL) {
   1557 		wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
   1558 			   __func__);
   1559 		reply = wpas_dbus_error_unknown_error(
   1560 			message,
   1561 			"wpa_supplicant could not add a network on this interface.");
   1562 		goto err;
   1563 	}
   1564 
   1565 	dbus_error_init(&error);
   1566 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
   1567 		wpa_printf(MSG_DEBUG,
   1568 			   "%s[dbus]: control interface couldn't set network properties",
   1569 			   __func__);
   1570 		reply = wpas_dbus_reply_new_from_error(message, &error,
   1571 						       DBUS_ERROR_INVALID_ARGS,
   1572 						       "Failed to add network");
   1573 		dbus_error_free(&error);
   1574 		goto err;
   1575 	}
   1576 
   1577 	/* Construct the object path for this network. */
   1578 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
   1579 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
   1580 		    wpa_s->dbus_new_path, ssid->id);
   1581 
   1582 	reply = dbus_message_new_method_return(message);
   1583 	if (reply == NULL) {
   1584 		reply = wpas_dbus_error_no_memory(message);
   1585 		goto err;
   1586 	}
   1587 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
   1588 				      DBUS_TYPE_INVALID)) {
   1589 		dbus_message_unref(reply);
   1590 		reply = wpas_dbus_error_no_memory(message);
   1591 		goto err;
   1592 	}
   1593 
   1594 	return reply;
   1595 
   1596 err:
   1597 	if (ssid) {
   1598 		wpas_notify_network_removed(wpa_s, ssid);
   1599 		wpa_config_remove_network(wpa_s->conf, ssid->id);
   1600 	}
   1601 	return reply;
   1602 }
   1603 
   1604 
   1605 /**
   1606  * wpas_dbus_handler_reassociate - Reassociate
   1607  * @message: Pointer to incoming dbus message
   1608  * @wpa_s: wpa_supplicant structure for a network interface
   1609  * Returns: InterfaceDisabled DBus error message if disabled
   1610  * or NULL otherwise.
   1611  *
   1612  * Handler function for "Reassociate" method call of network interface.
   1613  */
   1614 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
   1615 					    struct wpa_supplicant *wpa_s)
   1616 {
   1617 	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) {
   1618 		wpas_request_connection(wpa_s);
   1619 		return NULL;
   1620 	}
   1621 
   1622 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED,
   1623 				      "This interface is disabled");
   1624 }
   1625 
   1626 
   1627 /**
   1628  * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
   1629  * @message: Pointer to incoming dbus message
   1630  * @global: %wpa_supplicant global data structure
   1631  * Returns: NULL
   1632  *
   1633  * Handler function for notifying system there will be a expected disconnect.
   1634  * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
   1635  */
   1636 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
   1637 						  struct wpa_global *global)
   1638 {
   1639 	struct wpa_supplicant *wpa_s = global->ifaces;
   1640 
   1641 	for (; wpa_s; wpa_s = wpa_s->next)
   1642 		if (wpa_s->wpa_state >= WPA_ASSOCIATED)
   1643 			wpa_s->own_disconnect_req = 1;
   1644 	return NULL;
   1645 }
   1646 
   1647 
   1648 /**
   1649  * wpas_dbus_handler_reattach - Reattach to current AP
   1650  * @message: Pointer to incoming dbus message
   1651  * @wpa_s: wpa_supplicant structure for a network interface
   1652  * Returns: NotConnected DBus error message if not connected
   1653  * or NULL otherwise.
   1654  *
   1655  * Handler function for "Reattach" method call of network interface.
   1656  */
   1657 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
   1658 					 struct wpa_supplicant *wpa_s)
   1659 {
   1660 	if (wpa_s->current_ssid != NULL) {
   1661 		wpa_s->reattach = 1;
   1662 		wpas_request_connection(wpa_s);
   1663 		return NULL;
   1664 	}
   1665 
   1666 	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
   1667 				      "This interface is not connected");
   1668 }
   1669 
   1670 
   1671 /**
   1672  * wpas_dbus_handler_reconnect - Reconnect if disconnected
   1673  * @message: Pointer to incoming dbus message
   1674  * @wpa_s: wpa_supplicant structure for a network interface
   1675  * Returns: InterfaceDisabled DBus error message if disabled
   1676  * or NULL otherwise.
   1677  *
   1678  * Handler function for "Reconnect" method call of network interface.
   1679  */
   1680 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
   1681 		struct wpa_supplicant *wpa_s)
   1682 {
   1683 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
   1684 		return dbus_message_new_error(message,
   1685 					      WPAS_DBUS_ERROR_IFACE_DISABLED,
   1686 					      "This interface is disabled");
   1687 	}
   1688 
   1689 	if (wpa_s->disconnected)
   1690 		wpas_request_connection(wpa_s);
   1691 	return NULL;
   1692 }
   1693 
   1694 
   1695 /**
   1696  * wpas_dbus_handler_remove_network - Remove a configured network
   1697  * @message: Pointer to incoming dbus message
   1698  * @wpa_s: wpa_supplicant structure for a network interface
   1699  * Returns: NULL on success or dbus error on failure
   1700  *
   1701  * Handler function for "RemoveNetwork" method call of a network interface.
   1702  */
   1703 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
   1704 					       struct wpa_supplicant *wpa_s)
   1705 {
   1706 	DBusMessage *reply = NULL;
   1707 	const char *op;
   1708 	char *iface, *net_id;
   1709 	int id;
   1710 	int result;
   1711 
   1712 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
   1713 			      DBUS_TYPE_INVALID);
   1714 
   1715 	/* Extract the network ID and ensure the network */
   1716 	/* is actually a child of this interface */
   1717 	iface = wpas_dbus_new_decompose_object_path(op,
   1718 						    WPAS_DBUS_NEW_NETWORKS_PART,
   1719 						    &net_id);
   1720 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
   1721 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
   1722 		reply = wpas_dbus_error_invalid_args(message, op);
   1723 		goto out;
   1724 	}
   1725 
   1726 	errno = 0;
   1727 	id = strtoul(net_id, NULL, 10);
   1728 	if (errno != 0) {
   1729 		reply = wpas_dbus_error_invalid_args(message, op);
   1730 		goto out;
   1731 	}
   1732 
   1733 	result = wpa_supplicant_remove_network(wpa_s, id);
   1734 	if (result == -1) {
   1735 		reply = wpas_dbus_error_network_unknown(message);
   1736 		goto out;
   1737 	}
   1738 	if (result == -2) {
   1739 		wpa_printf(MSG_ERROR,
   1740 			   "%s[dbus]: error occurred when removing network %d",
   1741 			   __func__, id);
   1742 		reply = wpas_dbus_error_unknown_error(
   1743 			message,
   1744 			"error removing the specified network on is interface.");
   1745 		goto out;
   1746 	}
   1747 
   1748 out:
   1749 	os_free(iface);
   1750 	return reply;
   1751 }
   1752 
   1753 
   1754 static void remove_network(void *arg, struct wpa_ssid *ssid)
   1755 {
   1756 	struct wpa_supplicant *wpa_s = arg;
   1757 
   1758 	wpas_notify_network_removed(wpa_s, ssid);
   1759 
   1760 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
   1761 		wpa_printf(MSG_ERROR,
   1762 			   "%s[dbus]: error occurred when removing network %d",
   1763 			   __func__, ssid->id);
   1764 		return;
   1765 	}
   1766 
   1767 	if (ssid == wpa_s->current_ssid)
   1768 		wpa_supplicant_deauthenticate(wpa_s,
   1769 					      WLAN_REASON_DEAUTH_LEAVING);
   1770 }
   1771 
   1772 
   1773 /**
   1774  * wpas_dbus_handler_remove_all_networks - Remove all configured networks
   1775  * @message: Pointer to incoming dbus message
   1776  * @wpa_s: wpa_supplicant structure for a network interface
   1777  * Returns: NULL on success or dbus error on failure
   1778  *
   1779  * Handler function for "RemoveAllNetworks" method call of a network interface.
   1780  */
   1781 DBusMessage * wpas_dbus_handler_remove_all_networks(
   1782 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   1783 {
   1784 	if (wpa_s->sched_scanning)
   1785 		wpa_supplicant_cancel_sched_scan(wpa_s);
   1786 
   1787 	/* NB: could check for failure and return an error */
   1788 	wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
   1789 	return NULL;
   1790 }
   1791 
   1792 
   1793 /**
   1794  * wpas_dbus_handler_select_network - Attempt association with a network
   1795  * @message: Pointer to incoming dbus message
   1796  * @wpa_s: wpa_supplicant structure for a network interface
   1797  * Returns: NULL on success or dbus error on failure
   1798  *
   1799  * Handler function for "SelectNetwork" method call of network interface.
   1800  */
   1801 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
   1802 					       struct wpa_supplicant *wpa_s)
   1803 {
   1804 	DBusMessage *reply = NULL;
   1805 	const char *op;
   1806 	char *iface, *net_id;
   1807 	int id;
   1808 	struct wpa_ssid *ssid;
   1809 
   1810 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
   1811 			      DBUS_TYPE_INVALID);
   1812 
   1813 	/* Extract the network ID and ensure the network */
   1814 	/* is actually a child of this interface */
   1815 	iface = wpas_dbus_new_decompose_object_path(op,
   1816 						    WPAS_DBUS_NEW_NETWORKS_PART,
   1817 						    &net_id);
   1818 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
   1819 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
   1820 		reply = wpas_dbus_error_invalid_args(message, op);
   1821 		goto out;
   1822 	}
   1823 
   1824 	errno = 0;
   1825 	id = strtoul(net_id, NULL, 10);
   1826 	if (errno != 0) {
   1827 		reply = wpas_dbus_error_invalid_args(message, op);
   1828 		goto out;
   1829 	}
   1830 
   1831 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1832 	if (ssid == NULL) {
   1833 		reply = wpas_dbus_error_network_unknown(message);
   1834 		goto out;
   1835 	}
   1836 
   1837 	/* Finally, associate with the network */
   1838 	wpa_supplicant_select_network(wpa_s, ssid);
   1839 
   1840 out:
   1841 	os_free(iface);
   1842 	return reply;
   1843 }
   1844 
   1845 
   1846 /**
   1847  * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal
   1848  * @message: Pointer to incoming dbus message
   1849  * @wpa_s: wpa_supplicant structure for a network interface
   1850  * Returns: NULL on success or dbus error on failure
   1851  *
   1852  * Handler function for "NetworkReply" method call of network interface.
   1853  */
   1854 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
   1855 					      struct wpa_supplicant *wpa_s)
   1856 {
   1857 #ifdef IEEE8021X_EAPOL
   1858 	DBusMessage *reply = NULL;
   1859 	const char *op, *field, *value;
   1860 	char *iface, *net_id;
   1861 	int id;
   1862 	struct wpa_ssid *ssid;
   1863 
   1864 	if (!dbus_message_get_args(message, NULL,
   1865 				   DBUS_TYPE_OBJECT_PATH, &op,
   1866 				   DBUS_TYPE_STRING, &field,
   1867 				   DBUS_TYPE_STRING, &value,
   1868 				   DBUS_TYPE_INVALID))
   1869 		return wpas_dbus_error_invalid_args(message, NULL);
   1870 
   1871 	/* Extract the network ID and ensure the network */
   1872 	/* is actually a child of this interface */
   1873 	iface = wpas_dbus_new_decompose_object_path(op,
   1874 						    WPAS_DBUS_NEW_NETWORKS_PART,
   1875 						    &net_id);
   1876 	if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
   1877 	    os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
   1878 		reply = wpas_dbus_error_invalid_args(message, op);
   1879 		goto out;
   1880 	}
   1881 
   1882 	errno = 0;
   1883 	id = strtoul(net_id, NULL, 10);
   1884 	if (errno != 0) {
   1885 		reply = wpas_dbus_error_invalid_args(message, net_id);
   1886 		goto out;
   1887 	}
   1888 
   1889 	ssid = wpa_config_get_network(wpa_s->conf, id);
   1890 	if (ssid == NULL) {
   1891 		reply = wpas_dbus_error_network_unknown(message);
   1892 		goto out;
   1893 	}
   1894 
   1895 	if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid,
   1896 						      field, value) < 0)
   1897 		reply = wpas_dbus_error_invalid_args(message, field);
   1898 	else {
   1899 		/* Tell EAP to retry immediately */
   1900 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
   1901 	}
   1902 
   1903 out:
   1904 	os_free(iface);
   1905 	return reply;
   1906 #else /* IEEE8021X_EAPOL */
   1907 	wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
   1908 	return wpas_dbus_error_unknown_error(message, "802.1X not included");
   1909 #endif /* IEEE8021X_EAPOL */
   1910 }
   1911 
   1912 
   1913 #ifndef CONFIG_NO_CONFIG_BLOBS
   1914 
   1915 /**
   1916  * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
   1917  * @message: Pointer to incoming dbus message
   1918  * @wpa_s: %wpa_supplicant data structure
   1919  * Returns: A dbus message containing an error on failure or NULL on success
   1920  *
   1921  * Asks wpa_supplicant to internally store a binary blobs.
   1922  */
   1923 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
   1924 					 struct wpa_supplicant *wpa_s)
   1925 {
   1926 	DBusMessage *reply = NULL;
   1927 	DBusMessageIter	iter, array_iter;
   1928 
   1929 	char *blob_name;
   1930 	u8 *blob_data;
   1931 	int blob_len;
   1932 	struct wpa_config_blob *blob = NULL;
   1933 
   1934 	dbus_message_iter_init(message, &iter);
   1935 	dbus_message_iter_get_basic(&iter, &blob_name);
   1936 
   1937 	if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
   1938 		return dbus_message_new_error(message,
   1939 					      WPAS_DBUS_ERROR_BLOB_EXISTS,
   1940 					      NULL);
   1941 	}
   1942 
   1943 	dbus_message_iter_next(&iter);
   1944 	dbus_message_iter_recurse(&iter, &array_iter);
   1945 
   1946 	dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
   1947 
   1948 	blob = os_zalloc(sizeof(*blob));
   1949 	if (!blob) {
   1950 		reply = wpas_dbus_error_no_memory(message);
   1951 		goto err;
   1952 	}
   1953 
   1954 	blob->data = os_memdup(blob_data, blob_len);
   1955 	blob->name = os_strdup(blob_name);
   1956 	if (!blob->data || !blob->name) {
   1957 		reply = wpas_dbus_error_no_memory(message);
   1958 		goto err;
   1959 	}
   1960 	blob->len = blob_len;
   1961 
   1962 	wpa_config_set_blob(wpa_s->conf, blob);
   1963 	wpas_notify_blob_added(wpa_s, blob->name);
   1964 
   1965 	return reply;
   1966 
   1967 err:
   1968 	if (blob) {
   1969 		os_free(blob->name);
   1970 		os_free(blob->data);
   1971 		os_free(blob);
   1972 	}
   1973 	return reply;
   1974 }
   1975 
   1976 
   1977 /**
   1978  * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
   1979  * @message: Pointer to incoming dbus message
   1980  * @wpa_s: %wpa_supplicant data structure
   1981  * Returns: A dbus message containing array of bytes (blob)
   1982  *
   1983  * Gets one wpa_supplicant's binary blobs.
   1984  */
   1985 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
   1986 					 struct wpa_supplicant *wpa_s)
   1987 {
   1988 	DBusMessage *reply = NULL;
   1989 	DBusMessageIter	iter, array_iter;
   1990 
   1991 	char *blob_name;
   1992 	const struct wpa_config_blob *blob;
   1993 
   1994 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
   1995 			      DBUS_TYPE_INVALID);
   1996 
   1997 	blob = wpa_config_get_blob(wpa_s->conf, blob_name);
   1998 	if (!blob) {
   1999 		return dbus_message_new_error(message,
   2000 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
   2001 					      "Blob id not set");
   2002 	}
   2003 
   2004 	reply = dbus_message_new_method_return(message);
   2005 	if (!reply)
   2006 		return wpas_dbus_error_no_memory(message);
   2007 
   2008 	dbus_message_iter_init_append(reply, &iter);
   2009 
   2010 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
   2011 					      DBUS_TYPE_BYTE_AS_STRING,
   2012 					      &array_iter) ||
   2013 	    !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
   2014 						  &(blob->data), blob->len) ||
   2015 	    !dbus_message_iter_close_container(&iter, &array_iter)) {
   2016 		dbus_message_unref(reply);
   2017 		reply = wpas_dbus_error_no_memory(message);
   2018 	}
   2019 
   2020 	return reply;
   2021 }
   2022 
   2023 
   2024 /**
   2025  * wpas_remove_handler_remove_blob - Remove named binary blob
   2026  * @message: Pointer to incoming dbus message
   2027  * @wpa_s: %wpa_supplicant data structure
   2028  * Returns: NULL on success or dbus error
   2029  *
   2030  * Asks wpa_supplicant to internally remove a binary blobs.
   2031  */
   2032 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
   2033 					    struct wpa_supplicant *wpa_s)
   2034 {
   2035 	DBusMessage *reply = NULL;
   2036 	char *blob_name;
   2037 
   2038 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
   2039 			      DBUS_TYPE_INVALID);
   2040 
   2041 	if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
   2042 		return dbus_message_new_error(message,
   2043 					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
   2044 					      "Blob id not set");
   2045 	}
   2046 	wpas_notify_blob_removed(wpa_s, blob_name);
   2047 
   2048 	return reply;
   2049 
   2050 }
   2051 
   2052 #endif /* CONFIG_NO_CONFIG_BLOBS */
   2053 
   2054 
   2055 /*
   2056  * wpas_dbus_handler_flush_bss - Flush the BSS cache
   2057  * @message: Pointer to incoming dbus message
   2058  * @wpa_s: wpa_supplicant structure for a network interface
   2059  * Returns: NULL
   2060  *
   2061  * Handler function for "FlushBSS" method call of network interface.
   2062  */
   2063 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
   2064 					  struct wpa_supplicant *wpa_s)
   2065 {
   2066 	dbus_uint32_t age;
   2067 
   2068 	dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
   2069 			      DBUS_TYPE_INVALID);
   2070 
   2071 	if (age == 0)
   2072 		wpa_bss_flush(wpa_s);
   2073 	else
   2074 		wpa_bss_flush_by_age(wpa_s, age);
   2075 
   2076 	return NULL;
   2077 }
   2078 
   2079 
   2080 #ifdef CONFIG_AUTOSCAN
   2081 /**
   2082  * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface
   2083  * @message: Pointer to incoming dbus message
   2084  * @wpa_s: wpa_supplicant structure for a network interface
   2085  * Returns: NULL
   2086  *
   2087  * Handler function for "AutoScan" method call of network interface.
   2088  */
   2089 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
   2090 					 struct wpa_supplicant *wpa_s)
   2091 {
   2092 	DBusMessage *reply = NULL;
   2093 	enum wpa_states state = wpa_s->wpa_state;
   2094 	char *arg;
   2095 
   2096 	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg,
   2097 			      DBUS_TYPE_INVALID);
   2098 
   2099 	if (arg != NULL && os_strlen(arg) > 0) {
   2100 		char *tmp;
   2101 
   2102 		tmp = os_strdup(arg);
   2103 		if (tmp == NULL) {
   2104 			reply = wpas_dbus_error_no_memory(message);
   2105 		} else {
   2106 			os_free(wpa_s->conf->autoscan);
   2107 			wpa_s->conf->autoscan = tmp;
   2108 			if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
   2109 				autoscan_init(wpa_s, 1);
   2110 			else if (state == WPA_SCANNING)
   2111 				wpa_supplicant_reinit_autoscan(wpa_s);
   2112 		}
   2113 	} else if (arg != NULL && os_strlen(arg) == 0) {
   2114 		os_free(wpa_s->conf->autoscan);
   2115 		wpa_s->conf->autoscan = NULL;
   2116 		autoscan_deinit(wpa_s);
   2117 	} else
   2118 		reply = dbus_message_new_error(message,
   2119 					       DBUS_ERROR_INVALID_ARGS,
   2120 					       NULL);
   2121 
   2122 	return reply;
   2123 }
   2124 #endif /* CONFIG_AUTOSCAN */
   2125 
   2126 
   2127 /*
   2128  * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff
   2129  * @message: Pointer to incoming dbus message
   2130  * @wpa_s: wpa_supplicant structure for a network interface
   2131  * Returns: NULL
   2132  *
   2133  * Handler function for "EAPLogoff" method call of network interface.
   2134  */
   2135 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
   2136 					   struct wpa_supplicant *wpa_s)
   2137 {
   2138 	eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
   2139 	return NULL;
   2140 }
   2141 
   2142 
   2143 /*
   2144  * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon
   2145  * @message: Pointer to incoming dbus message
   2146  * @wpa_s: wpa_supplicant structure for a network interface
   2147  * Returns: NULL
   2148  *
   2149  * Handler function for "EAPLogin" method call of network interface.
   2150  */
   2151 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
   2152 					  struct wpa_supplicant *wpa_s)
   2153 {
   2154 	eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
   2155 	return NULL;
   2156 }
   2157 
   2158 
   2159 #ifdef CONFIG_TDLS
   2160 
   2161 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name,
   2162 				  u8 *peer_address, DBusMessage **error)
   2163 {
   2164 	const char *peer_string;
   2165 
   2166 	*error = NULL;
   2167 
   2168 	if (!dbus_message_get_args(message, NULL,
   2169 				   DBUS_TYPE_STRING, &peer_string,
   2170 				   DBUS_TYPE_INVALID)) {
   2171 		*error = wpas_dbus_error_invalid_args(message, NULL);
   2172 		return -1;
   2173 	}
   2174 
   2175 	if (hwaddr_aton(peer_string, peer_address)) {
   2176 		wpa_printf(MSG_DEBUG, "%s: invalid address '%s'",
   2177 			   func_name, peer_string);
   2178 		*error = wpas_dbus_error_invalid_args(
   2179 			message, "Invalid hardware address format");
   2180 		return -1;
   2181 	}
   2182 
   2183 	return 0;
   2184 }
   2185 
   2186 
   2187 /*
   2188  * wpas_dbus_handler_tdls_discover - Discover TDLS peer
   2189  * @message: Pointer to incoming dbus message
   2190  * @wpa_s: wpa_supplicant structure for a network interface
   2191  * Returns: NULL indicating success or DBus error message on failure
   2192  *
   2193  * Handler function for "TDLSDiscover" method call of network interface.
   2194  */
   2195 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
   2196 					      struct wpa_supplicant *wpa_s)
   2197 {
   2198 	u8 peer[ETH_ALEN];
   2199 	DBusMessage *error_reply;
   2200 	int ret;
   2201 
   2202 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
   2203 		return error_reply;
   2204 
   2205 	wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer));
   2206 
   2207 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
   2208 		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
   2209 	else
   2210 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
   2211 
   2212 	if (ret) {
   2213 		return wpas_dbus_error_unknown_error(
   2214 			message, "error performing TDLS discovery");
   2215 	}
   2216 
   2217 	return NULL;
   2218 }
   2219 
   2220 
   2221 /*
   2222  * wpas_dbus_handler_tdls_setup - Setup TDLS session
   2223  * @message: Pointer to incoming dbus message
   2224  * @wpa_s: wpa_supplicant structure for a network interface
   2225  * Returns: NULL indicating success or DBus error message on failure
   2226  *
   2227  * Handler function for "TDLSSetup" method call of network interface.
   2228  */
   2229 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
   2230 					   struct wpa_supplicant *wpa_s)
   2231 {
   2232 	u8 peer[ETH_ALEN];
   2233 	DBusMessage *error_reply;
   2234 	int ret;
   2235 
   2236 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
   2237 		return error_reply;
   2238 
   2239 	wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer));
   2240 
   2241 	wpa_tdls_remove(wpa_s->wpa, peer);
   2242 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
   2243 		ret = wpa_tdls_start(wpa_s->wpa, peer);
   2244 	else
   2245 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
   2246 
   2247 	if (ret) {
   2248 		return wpas_dbus_error_unknown_error(
   2249 			message, "error performing TDLS setup");
   2250 	}
   2251 
   2252 	return NULL;
   2253 }
   2254 
   2255 
   2256 /*
   2257  * wpas_dbus_handler_tdls_status - Return TDLS session status
   2258  * @message: Pointer to incoming dbus message
   2259  * @wpa_s: wpa_supplicant structure for a network interface
   2260  * Returns: A string representing the state of the link to this TDLS peer
   2261  *
   2262  * Handler function for "TDLSStatus" method call of network interface.
   2263  */
   2264 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
   2265 					    struct wpa_supplicant *wpa_s)
   2266 {
   2267 	u8 peer[ETH_ALEN];
   2268 	DBusMessage *reply;
   2269 	const char *tdls_status;
   2270 
   2271 	if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0)
   2272 		return reply;
   2273 
   2274 	wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer));
   2275 
   2276 	tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer);
   2277 
   2278 	reply = dbus_message_new_method_return(message);
   2279 	dbus_message_append_args(reply, DBUS_TYPE_STRING,
   2280 				 &tdls_status, DBUS_TYPE_INVALID);
   2281 	return reply;
   2282 }
   2283 
   2284 
   2285 /*
   2286  * wpas_dbus_handler_tdls_teardown - Teardown TDLS session
   2287  * @message: Pointer to incoming dbus message
   2288  * @wpa_s: wpa_supplicant structure for a network interface
   2289  * Returns: NULL indicating success or DBus error message on failure
   2290  *
   2291  * Handler function for "TDLSTeardown" method call of network interface.
   2292  */
   2293 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
   2294 					      struct wpa_supplicant *wpa_s)
   2295 {
   2296 	u8 peer[ETH_ALEN];
   2297 	DBusMessage *error_reply;
   2298 	int ret;
   2299 
   2300 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
   2301 		return error_reply;
   2302 
   2303 	wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer));
   2304 
   2305 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
   2306 		ret = wpa_tdls_teardown_link(
   2307 			wpa_s->wpa, peer,
   2308 			WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
   2309 	else
   2310 		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
   2311 
   2312 	if (ret) {
   2313 		return wpas_dbus_error_unknown_error(
   2314 			message, "error performing TDLS teardown");
   2315 	}
   2316 
   2317 	return NULL;
   2318 }
   2319 
   2320 /*
   2321  * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
   2322  * @message: Pointer to incoming dbus message
   2323  * @wpa_s: wpa_supplicant structure for a network interface
   2324  * Returns: NULL indicating success or DBus error message on failure
   2325  *
   2326  * Handler function for "TDLSChannelSwitch" method call of network interface.
   2327  */
   2328 DBusMessage *
   2329 wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
   2330 				      struct wpa_supplicant *wpa_s)
   2331 {
   2332 	DBusMessageIter	iter, iter_dict;
   2333 	struct wpa_dbus_dict_entry entry;
   2334 	u8 peer[ETH_ALEN];
   2335 	struct hostapd_freq_params freq_params;
   2336 	u8 oper_class = 0;
   2337 	int ret;
   2338 	int is_peer_present = 0;
   2339 
   2340 	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
   2341 		wpa_printf(MSG_INFO,
   2342 			   "tdls_chanswitch: Only supported with external setup");
   2343 		return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup");
   2344 	}
   2345 
   2346 	os_memset(&freq_params, 0, sizeof(freq_params));
   2347 
   2348 	dbus_message_iter_init(message, &iter);
   2349 
   2350 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
   2351 		return wpas_dbus_error_invalid_args(message, NULL);
   2352 
   2353 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2354 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2355 			return wpas_dbus_error_invalid_args(message, NULL);
   2356 
   2357 		if (os_strcmp(entry.key, "PeerAddress") == 0 &&
   2358 		    entry.type == DBUS_TYPE_STRING) {
   2359 			if (hwaddr_aton(entry.str_value, peer)) {
   2360 				wpa_printf(MSG_DEBUG,
   2361 					   "tdls_chanswitch: Invalid address '%s'",
   2362 					   entry.str_value);
   2363 				wpa_dbus_dict_entry_clear(&entry);
   2364 				return wpas_dbus_error_invalid_args(message,
   2365 								    NULL);
   2366 			}
   2367 
   2368 			is_peer_present = 1;
   2369 		} else if (os_strcmp(entry.key, "OperClass") == 0 &&
   2370 			   entry.type == DBUS_TYPE_BYTE) {
   2371 			oper_class = entry.byte_value;
   2372 		} else if (os_strcmp(entry.key, "Frequency") == 0 &&
   2373 			   entry.type == DBUS_TYPE_UINT32) {
   2374 			freq_params.freq = entry.uint32_value;
   2375 		} else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
   2376 			   entry.type == DBUS_TYPE_UINT32) {
   2377 			freq_params.sec_channel_offset = entry.uint32_value;
   2378 		} else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
   2379 			   entry.type == DBUS_TYPE_UINT32) {
   2380 			freq_params.center_freq1 = entry.uint32_value;
   2381 		} else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
   2382 			   entry.type == DBUS_TYPE_UINT32) {
   2383 			freq_params.center_freq2 = entry.uint32_value;
   2384 		} else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
   2385 			   entry.type == DBUS_TYPE_UINT32) {
   2386 			freq_params.bandwidth = entry.uint32_value;
   2387 		} else if (os_strcmp(entry.key, "HT") == 0 &&
   2388 			   entry.type == DBUS_TYPE_BOOLEAN) {
   2389 			freq_params.ht_enabled = entry.bool_value;
   2390 		} else if (os_strcmp(entry.key, "VHT") == 0 &&
   2391 			   entry.type == DBUS_TYPE_BOOLEAN) {
   2392 			freq_params.vht_enabled = entry.bool_value;
   2393 		} else {
   2394 			wpa_dbus_dict_entry_clear(&entry);
   2395 			return wpas_dbus_error_invalid_args(message, NULL);
   2396 		}
   2397 
   2398 		wpa_dbus_dict_entry_clear(&entry);
   2399 	}
   2400 
   2401 	if (oper_class == 0) {
   2402 		wpa_printf(MSG_INFO,
   2403 			   "tdls_chanswitch: Invalid op class provided");
   2404 		return wpas_dbus_error_invalid_args(
   2405 			message, "Invalid op class provided");
   2406 	}
   2407 
   2408 	if (freq_params.freq == 0) {
   2409 		wpa_printf(MSG_INFO,
   2410 			   "tdls_chanswitch: Invalid freq provided");
   2411 		return wpas_dbus_error_invalid_args(message,
   2412 						    "Invalid freq provided");
   2413 	}
   2414 
   2415 	if (is_peer_present == 0) {
   2416 		wpa_printf(MSG_DEBUG,
   2417 			   "tdls_chanswitch: peer address not provided");
   2418 		return wpas_dbus_error_invalid_args(
   2419 			message, "peer address not provided");
   2420 	}
   2421 
   2422 	wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR
   2423 		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
   2424 		   MAC2STR(peer), oper_class, freq_params.freq,
   2425 		   freq_params.center_freq1, freq_params.center_freq2,
   2426 		   freq_params.bandwidth, freq_params.sec_channel_offset,
   2427 		   freq_params.ht_enabled ? " HT" : "",
   2428 		   freq_params.vht_enabled ? " VHT" : "");
   2429 
   2430 	ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
   2431 					  &freq_params);
   2432 	if (ret)
   2433 		return wpas_dbus_error_unknown_error(
   2434 			message, "error processing TDLS channel switch");
   2435 
   2436 	return NULL;
   2437 }
   2438 
   2439 /*
   2440  * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer
   2441  * @message: Pointer to incoming dbus message
   2442  * @wpa_s: wpa_supplicant structure for a network interface
   2443  * Returns: NULL indicating success or DBus error message on failure
   2444  *
   2445  * Handler function for "TDLSCancelChannelSwitch" method call of network
   2446  * interface.
   2447  */
   2448 DBusMessage *
   2449 wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
   2450 					     struct wpa_supplicant *wpa_s)
   2451 {
   2452 	u8 peer[ETH_ALEN];
   2453 	DBusMessage *error_reply;
   2454 	int ret;
   2455 
   2456 	if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0)
   2457 		return error_reply;
   2458 
   2459 	wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR,
   2460 		   MAC2STR(peer));
   2461 
   2462 	ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer);
   2463 	if (ret)
   2464 		return wpas_dbus_error_unknown_error(
   2465 			message, "error canceling TDLS channel switch");
   2466 
   2467 	return NULL;
   2468 }
   2469 
   2470 #endif /* CONFIG_TDLS */
   2471 
   2472 
   2473 #ifndef CONFIG_NO_CONFIG_WRITE
   2474 /**
   2475  * wpas_dbus_handler_save_config - Save configuration to configuration file
   2476  * @message: Pointer to incoming dbus message
   2477  * @wpa_s: wpa_supplicant structure for a network interface
   2478  * Returns: NULL on Success, Otherwise errror message
   2479  *
   2480  * Handler function for "SaveConfig" method call of network interface.
   2481  */
   2482 DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
   2483 					    struct wpa_supplicant *wpa_s)
   2484 {
   2485 	int ret;
   2486 
   2487 	if (!wpa_s->conf->update_config) {
   2488 		return wpas_dbus_error_unknown_error(
   2489 			message,
   2490 			"Not allowed to update configuration (update_config=0)");
   2491 	}
   2492 
   2493 	ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
   2494 	if (ret)
   2495 		return wpas_dbus_error_unknown_error(
   2496 			message, "Failed to update configuration");
   2497 	return NULL;
   2498 }
   2499 #endif /* CONFIG_NO_CONFIG_WRITE */
   2500 
   2501 
   2502 /**
   2503  * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
   2504  * @message: Pointer to incoming dbus message
   2505  * @wpa_s: %wpa_supplicant data structure
   2506  * Returns: A dbus message containing an error on failure or NULL on success
   2507  *
   2508  * Sets the PKCS #11 engine and module path.
   2509  */
   2510 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
   2511 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2512 {
   2513 	DBusMessageIter iter;
   2514 	char *value = NULL;
   2515 	char *pkcs11_engine_path = NULL;
   2516 	char *pkcs11_module_path = NULL;
   2517 
   2518 	dbus_message_iter_init(message, &iter);
   2519 	dbus_message_iter_get_basic(&iter, &value);
   2520 	if (value == NULL) {
   2521 		return dbus_message_new_error(
   2522 			message, DBUS_ERROR_INVALID_ARGS,
   2523 			"Invalid pkcs11_engine_path argument");
   2524 	}
   2525 	/* Empty path defaults to NULL */
   2526 	if (os_strlen(value))
   2527 		pkcs11_engine_path = value;
   2528 
   2529 	dbus_message_iter_next(&iter);
   2530 	dbus_message_iter_get_basic(&iter, &value);
   2531 	if (value == NULL) {
   2532 		os_free(pkcs11_engine_path);
   2533 		return dbus_message_new_error(
   2534 			message, DBUS_ERROR_INVALID_ARGS,
   2535 			"Invalid pkcs11_module_path argument");
   2536 	}
   2537 	/* Empty path defaults to NULL */
   2538 	if (os_strlen(value))
   2539 		pkcs11_module_path = value;
   2540 
   2541 	if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path,
   2542 						   pkcs11_module_path))
   2543 		return dbus_message_new_error(
   2544 			message, DBUS_ERROR_FAILED,
   2545 			"Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
   2546 
   2547 	if (wpa_s->dbus_new_path) {
   2548 		wpa_dbus_mark_property_changed(
   2549 			wpa_s->global->dbus, wpa_s->dbus_new_path,
   2550 			WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
   2551 		wpa_dbus_mark_property_changed(
   2552 			wpa_s->global->dbus, wpa_s->dbus_new_path,
   2553 			WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
   2554 	}
   2555 
   2556 	return NULL;
   2557 }
   2558 
   2559 
   2560 /**
   2561  * wpas_dbus_getter_capabilities - Return interface capabilities
   2562  * @iter: Pointer to incoming dbus message iter
   2563  * @error: Location to store error on failure
   2564  * @user_data: Function specific data
   2565  * Returns: TRUE on success, FALSE on failure
   2566  *
   2567  * Getter for "Capabilities" property of an interface.
   2568  */
   2569 dbus_bool_t wpas_dbus_getter_capabilities(
   2570 	const struct wpa_dbus_property_desc *property_desc,
   2571 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2572 {
   2573 	struct wpa_supplicant *wpa_s = user_data;
   2574 	struct wpa_driver_capa capa;
   2575 	int res;
   2576 	DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array,
   2577 		variant_iter;
   2578 	const char *scans[] = { "active", "passive", "ssid" };
   2579 
   2580 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   2581 					      "a{sv}", &variant_iter) ||
   2582 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
   2583 		goto nomem;
   2584 
   2585 	res = wpa_drv_get_capa(wpa_s, &capa);
   2586 
   2587 	/***** pairwise cipher */
   2588 	if (res < 0) {
   2589 		const char *args[] = {"ccmp", "tkip", "none"};
   2590 
   2591 		if (!wpa_dbus_dict_append_string_array(
   2592 			    &iter_dict, "Pairwise", args,
   2593 			    ARRAY_SIZE(args)))
   2594 			goto nomem;
   2595 	} else {
   2596 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
   2597 						      &iter_dict_entry,
   2598 						      &iter_dict_val,
   2599 						      &iter_array) ||
   2600 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
   2601 		     !wpa_dbus_dict_string_array_add_element(
   2602 			     &iter_array, "ccmp-256")) ||
   2603 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
   2604 		     !wpa_dbus_dict_string_array_add_element(
   2605 			     &iter_array, "gcmp-256")) ||
   2606 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
   2607 		     !wpa_dbus_dict_string_array_add_element(
   2608 			     &iter_array, "ccmp")) ||
   2609 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
   2610 		     !wpa_dbus_dict_string_array_add_element(
   2611 			     &iter_array, "gcmp")) ||
   2612 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
   2613 		     !wpa_dbus_dict_string_array_add_element(
   2614 			     &iter_array, "tkip")) ||
   2615 		    ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
   2616 		     !wpa_dbus_dict_string_array_add_element(
   2617 			     &iter_array, "none")) ||
   2618 		    !wpa_dbus_dict_end_string_array(&iter_dict,
   2619 						    &iter_dict_entry,
   2620 						    &iter_dict_val,
   2621 						    &iter_array))
   2622 			goto nomem;
   2623 	}
   2624 
   2625 	/***** group cipher */
   2626 	if (res < 0) {
   2627 		const char *args[] = {
   2628 			"ccmp", "tkip", "wep104", "wep40"
   2629 		};
   2630 
   2631 		if (!wpa_dbus_dict_append_string_array(
   2632 			    &iter_dict, "Group", args,
   2633 			    ARRAY_SIZE(args)))
   2634 			goto nomem;
   2635 	} else {
   2636 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
   2637 						      &iter_dict_entry,
   2638 						      &iter_dict_val,
   2639 						      &iter_array) ||
   2640 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) &&
   2641 		     !wpa_dbus_dict_string_array_add_element(
   2642 			     &iter_array, "ccmp-256")) ||
   2643 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) &&
   2644 		     !wpa_dbus_dict_string_array_add_element(
   2645 			     &iter_array, "gcmp-256")) ||
   2646 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) &&
   2647 		     !wpa_dbus_dict_string_array_add_element(
   2648 			     &iter_array, "ccmp")) ||
   2649 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) &&
   2650 		     !wpa_dbus_dict_string_array_add_element(
   2651 			     &iter_array, "gcmp")) ||
   2652 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) &&
   2653 		     !wpa_dbus_dict_string_array_add_element(
   2654 			     &iter_array, "tkip")) ||
   2655 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) &&
   2656 		     !wpa_dbus_dict_string_array_add_element(
   2657 			     &iter_array, "wep104")) ||
   2658 		    ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) &&
   2659 		     !wpa_dbus_dict_string_array_add_element(
   2660 			     &iter_array, "wep40")) ||
   2661 		    !wpa_dbus_dict_end_string_array(&iter_dict,
   2662 						    &iter_dict_entry,
   2663 						    &iter_dict_val,
   2664 						    &iter_array))
   2665 			goto nomem;
   2666 	}
   2667 
   2668 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt",
   2669 					      &iter_dict_entry,
   2670 					      &iter_dict_val,
   2671 					      &iter_array) ||
   2672 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) &&
   2673 	     !wpa_dbus_dict_string_array_add_element(
   2674 		     &iter_array, "aes-128-cmac")) ||
   2675 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) &&
   2676 	     !wpa_dbus_dict_string_array_add_element(
   2677 		     &iter_array, "bip-gmac-128")) ||
   2678 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) &&
   2679 	     !wpa_dbus_dict_string_array_add_element(
   2680 		     &iter_array, "bip-gmac-256")) ||
   2681 	    (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) &&
   2682 	     !wpa_dbus_dict_string_array_add_element(
   2683 		     &iter_array, "bip-cmac-256")) ||
   2684 	    !wpa_dbus_dict_end_string_array(&iter_dict,
   2685 					    &iter_dict_entry,
   2686 					    &iter_dict_val,
   2687 					    &iter_array))
   2688 		goto nomem;
   2689 
   2690 	/***** key management */
   2691 	if (res < 0) {
   2692 		const char *args[] = {
   2693 			"wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
   2694 #ifdef CONFIG_WPS
   2695 			"wps",
   2696 #endif /* CONFIG_WPS */
   2697 			"none"
   2698 		};
   2699 		if (!wpa_dbus_dict_append_string_array(
   2700 			    &iter_dict, "KeyMgmt", args,
   2701 			    ARRAY_SIZE(args)))
   2702 			goto nomem;
   2703 	} else {
   2704 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
   2705 						      &iter_dict_entry,
   2706 						      &iter_dict_val,
   2707 						      &iter_array) ||
   2708 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
   2709 							    "none") ||
   2710 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
   2711 							    "ieee8021x"))
   2712 			goto nomem;
   2713 
   2714 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   2715 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
   2716 			if (!wpa_dbus_dict_string_array_add_element(
   2717 				    &iter_array, "wpa-eap") ||
   2718 			    ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) &&
   2719 			     !wpa_dbus_dict_string_array_add_element(
   2720 				     &iter_array, "wpa-ft-eap")))
   2721 				goto nomem;
   2722 
   2723 /* TODO: Ensure that driver actually supports sha256 encryption. */
   2724 #ifdef CONFIG_IEEE80211W
   2725 			if (!wpa_dbus_dict_string_array_add_element(
   2726 				    &iter_array, "wpa-eap-sha256"))
   2727 				goto nomem;
   2728 #endif /* CONFIG_IEEE80211W */
   2729 		}
   2730 
   2731 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
   2732 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
   2733 			if (!wpa_dbus_dict_string_array_add_element(
   2734 				    &iter_array, "wpa-psk") ||
   2735 			    ((capa.key_mgmt &
   2736 			      WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) &&
   2737 			     !wpa_dbus_dict_string_array_add_element(
   2738 				     &iter_array, "wpa-ft-psk")))
   2739 				goto nomem;
   2740 
   2741 /* TODO: Ensure that driver actually supports sha256 encryption. */
   2742 #ifdef CONFIG_IEEE80211W
   2743 			if (!wpa_dbus_dict_string_array_add_element(
   2744 				    &iter_array, "wpa-psk-sha256"))
   2745 				goto nomem;
   2746 #endif /* CONFIG_IEEE80211W */
   2747 		}
   2748 
   2749 		if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) &&
   2750 		    !wpa_dbus_dict_string_array_add_element(&iter_array,
   2751 							    "wpa-none"))
   2752 			goto nomem;
   2753 
   2754 
   2755 #ifdef CONFIG_WPS
   2756 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
   2757 							    "wps"))
   2758 			goto nomem;
   2759 #endif /* CONFIG_WPS */
   2760 
   2761 		if (!wpa_dbus_dict_end_string_array(&iter_dict,
   2762 						    &iter_dict_entry,
   2763 						    &iter_dict_val,
   2764 						    &iter_array))
   2765 			goto nomem;
   2766 	}
   2767 
   2768 	/***** WPA protocol */
   2769 	if (res < 0) {
   2770 		const char *args[] = { "rsn", "wpa" };
   2771 
   2772 		if (!wpa_dbus_dict_append_string_array(
   2773 			    &iter_dict, "Protocol", args,
   2774 			    ARRAY_SIZE(args)))
   2775 			goto nomem;
   2776 	} else {
   2777 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
   2778 						      &iter_dict_entry,
   2779 						      &iter_dict_val,
   2780 						      &iter_array) ||
   2781 		    ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
   2782 				       WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) &&
   2783 		     !wpa_dbus_dict_string_array_add_element(
   2784 			     &iter_array, "rsn")) ||
   2785 		    ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
   2786 				       WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) &&
   2787 		     !wpa_dbus_dict_string_array_add_element(
   2788 			     &iter_array, "wpa")) ||
   2789 		    !wpa_dbus_dict_end_string_array(&iter_dict,
   2790 						    &iter_dict_entry,
   2791 						    &iter_dict_val,
   2792 						    &iter_array))
   2793 			goto nomem;
   2794 	}
   2795 
   2796 	/***** auth alg */
   2797 	if (res < 0) {
   2798 		const char *args[] = { "open", "shared", "leap" };
   2799 
   2800 		if (!wpa_dbus_dict_append_string_array(
   2801 			    &iter_dict, "AuthAlg", args,
   2802 			    ARRAY_SIZE(args)))
   2803 			goto nomem;
   2804 	} else {
   2805 		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
   2806 						      &iter_dict_entry,
   2807 						      &iter_dict_val,
   2808 						      &iter_array))
   2809 			goto nomem;
   2810 
   2811 		if (((capa.auth & WPA_DRIVER_AUTH_OPEN) &&
   2812 		     !wpa_dbus_dict_string_array_add_element(
   2813 			     &iter_array, "open")) ||
   2814 		    ((capa.auth & WPA_DRIVER_AUTH_SHARED) &&
   2815 		     !wpa_dbus_dict_string_array_add_element(
   2816 			     &iter_array, "shared")) ||
   2817 		    ((capa.auth & WPA_DRIVER_AUTH_LEAP) &&
   2818 		     !wpa_dbus_dict_string_array_add_element(
   2819 			     &iter_array, "leap")) ||
   2820 		    !wpa_dbus_dict_end_string_array(&iter_dict,
   2821 						    &iter_dict_entry,
   2822 						    &iter_dict_val,
   2823 						    &iter_array))
   2824 			goto nomem;
   2825 	}
   2826 
   2827 	/***** Scan */
   2828 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
   2829 					       ARRAY_SIZE(scans)))
   2830 		goto nomem;
   2831 
   2832 	/***** Modes */
   2833 	if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes",
   2834 					      &iter_dict_entry,
   2835 					      &iter_dict_val,
   2836 					      &iter_array) ||
   2837 	    !wpa_dbus_dict_string_array_add_element(
   2838 		    &iter_array, "infrastructure") ||
   2839 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
   2840 	     !wpa_dbus_dict_string_array_add_element(
   2841 		     &iter_array, "ad-hoc")) ||
   2842 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
   2843 	     !wpa_dbus_dict_string_array_add_element(
   2844 		     &iter_array, "ap")) ||
   2845 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
   2846 	     !wpa_s->conf->p2p_disabled &&
   2847 	     !wpa_dbus_dict_string_array_add_element(
   2848 		     &iter_array, "p2p")) ||
   2849 #ifdef CONFIG_MESH
   2850 	    (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) &&
   2851 	     !wpa_dbus_dict_string_array_add_element(
   2852 		     &iter_array, "mesh")) ||
   2853 #endif /* CONFIG_MESH */
   2854 	    !wpa_dbus_dict_end_string_array(&iter_dict,
   2855 					    &iter_dict_entry,
   2856 					    &iter_dict_val,
   2857 					    &iter_array))
   2858 		goto nomem;
   2859 	/***** Modes end */
   2860 
   2861 	if (res >= 0) {
   2862 		dbus_int32_t max_scan_ssid = capa.max_scan_ssids;
   2863 
   2864 		if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID",
   2865 						max_scan_ssid))
   2866 			goto nomem;
   2867 	}
   2868 
   2869 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
   2870 	    !dbus_message_iter_close_container(iter, &variant_iter))
   2871 		goto nomem;
   2872 
   2873 	return TRUE;
   2874 
   2875 nomem:
   2876 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   2877 	return FALSE;
   2878 }
   2879 
   2880 
   2881 /**
   2882  * wpas_dbus_getter_state - Get interface state
   2883  * @iter: Pointer to incoming dbus message iter
   2884  * @error: Location to store error on failure
   2885  * @user_data: Function specific data
   2886  * Returns: TRUE on success, FALSE on failure
   2887  *
   2888  * Getter for "State" property.
   2889  */
   2890 dbus_bool_t wpas_dbus_getter_state(
   2891 	const struct wpa_dbus_property_desc *property_desc,
   2892 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2893 {
   2894 	struct wpa_supplicant *wpa_s = user_data;
   2895 	const char *str_state;
   2896 	char *state_ls, *tmp;
   2897 	dbus_bool_t success = FALSE;
   2898 
   2899 	str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
   2900 
   2901 	/* make state string lowercase to fit new DBus API convention
   2902 	 */
   2903 	state_ls = tmp = os_strdup(str_state);
   2904 	if (!tmp) {
   2905 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   2906 		return FALSE;
   2907 	}
   2908 	while (*tmp) {
   2909 		*tmp = tolower(*tmp);
   2910 		tmp++;
   2911 	}
   2912 
   2913 	success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
   2914 						   &state_ls, error);
   2915 
   2916 	os_free(state_ls);
   2917 
   2918 	return success;
   2919 }
   2920 
   2921 
   2922 /**
   2923  * wpas_dbus_new_iface_get_scanning - Get interface scanning state
   2924  * @iter: Pointer to incoming dbus message iter
   2925  * @error: Location to store error on failure
   2926  * @user_data: Function specific data
   2927  * Returns: TRUE on success, FALSE on failure
   2928  *
   2929  * Getter for "scanning" property.
   2930  */
   2931 dbus_bool_t wpas_dbus_getter_scanning(
   2932 	const struct wpa_dbus_property_desc *property_desc,
   2933 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2934 {
   2935 	struct wpa_supplicant *wpa_s = user_data;
   2936 	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
   2937 
   2938 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
   2939 						&scanning, error);
   2940 }
   2941 
   2942 
   2943 /**
   2944  * wpas_dbus_getter_ap_scan - Control roaming mode
   2945  * @iter: Pointer to incoming dbus message iter
   2946  * @error: Location to store error on failure
   2947  * @user_data: Function specific data
   2948  * Returns: TRUE on success, FALSE on failure
   2949  *
   2950  * Getter function for "ApScan" property.
   2951  */
   2952 dbus_bool_t wpas_dbus_getter_ap_scan(
   2953 	const struct wpa_dbus_property_desc *property_desc,
   2954 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2955 {
   2956 	struct wpa_supplicant *wpa_s = user_data;
   2957 	dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
   2958 
   2959 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
   2960 						&ap_scan, error);
   2961 }
   2962 
   2963 
   2964 /**
   2965  * wpas_dbus_setter_ap_scan - Control roaming mode
   2966  * @iter: Pointer to incoming dbus message iter
   2967  * @error: Location to store error on failure
   2968  * @user_data: Function specific data
   2969  * Returns: TRUE on success, FALSE on failure
   2970  *
   2971  * Setter function for "ApScan" property.
   2972  */
   2973 dbus_bool_t wpas_dbus_setter_ap_scan(
   2974 	const struct wpa_dbus_property_desc *property_desc,
   2975 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2976 {
   2977 	struct wpa_supplicant *wpa_s = user_data;
   2978 	dbus_uint32_t ap_scan;
   2979 
   2980 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
   2981 					      &ap_scan))
   2982 		return FALSE;
   2983 
   2984 	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
   2985 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   2986 				     "ap_scan must be 0, 1, or 2");
   2987 		return FALSE;
   2988 	}
   2989 	return TRUE;
   2990 }
   2991 
   2992 
   2993 #ifdef CONFIG_IEEE80211W
   2994 
   2995 /**
   2996  * wpas_dbus_getter_pmf - Control PMF default
   2997  * @iter: Pointer to incoming dbus message iter
   2998  * @error: Location to store error on failure
   2999  * @user_data: Function specific data
   3000  * Returns: TRUE on success, FALSE on failure
   3001  *
   3002  * Getter function for "Pmf" property.
   3003  */
   3004 dbus_bool_t wpas_dbus_getter_pmf(
   3005 	const struct wpa_dbus_property_desc *property_desc,
   3006 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3007 {
   3008 	struct wpa_supplicant *wpa_s = user_data;
   3009 	dbus_uint32_t pmf = wpa_s->conf->pmf;
   3010 
   3011 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
   3012 						&pmf, error);
   3013 }
   3014 
   3015 
   3016 /**
   3017  * wpas_dbus_setter_pmf - Control PMF default
   3018  * @iter: Pointer to incoming dbus message iter
   3019  * @error: Location to store error on failure
   3020  * @user_data: Function specific data
   3021  * Returns: TRUE on success, FALSE on failure
   3022  *
   3023  * Setter function for "Pmf" property.
   3024  */
   3025 dbus_bool_t wpas_dbus_setter_pmf(
   3026 	const struct wpa_dbus_property_desc *property_desc,
   3027 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3028 {
   3029 	struct wpa_supplicant *wpa_s = user_data;
   3030 	dbus_uint32_t pmf;
   3031 
   3032 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
   3033 					      &pmf))
   3034 		return FALSE;
   3035 
   3036 	if (pmf > 2) {
   3037 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3038 				     "Pmf must be 0, 1, or 2");
   3039 		return FALSE;
   3040 	}
   3041 	wpa_s->conf->pmf = pmf;
   3042 	return TRUE;
   3043 }
   3044 
   3045 #endif /* CONFIG_IEEE80211W */
   3046 
   3047 
   3048 /**
   3049  * wpas_dbus_getter_fast_reauth - Control fast
   3050  * reauthentication (TLS session resumption)
   3051  * @iter: Pointer to incoming dbus message iter
   3052  * @error: Location to store error on failure
   3053  * @user_data: Function specific data
   3054  * Returns: TRUE on success, FALSE on failure
   3055  *
   3056  * Getter function for "FastReauth" property.
   3057  */
   3058 dbus_bool_t wpas_dbus_getter_fast_reauth(
   3059 	const struct wpa_dbus_property_desc *property_desc,
   3060 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3061 {
   3062 	struct wpa_supplicant *wpa_s = user_data;
   3063 	dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
   3064 
   3065 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
   3066 						&fast_reauth, error);
   3067 }
   3068 
   3069 
   3070 /**
   3071  * wpas_dbus_setter_fast_reauth - Control fast
   3072  * reauthentication (TLS session resumption)
   3073  * @iter: Pointer to incoming dbus message iter
   3074  * @error: Location to store error on failure
   3075  * @user_data: Function specific data
   3076  * Returns: TRUE on success, FALSE on failure
   3077  *
   3078  * Setter function for "FastReauth" property.
   3079  */
   3080 dbus_bool_t wpas_dbus_setter_fast_reauth(
   3081 	const struct wpa_dbus_property_desc *property_desc,
   3082 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3083 {
   3084 	struct wpa_supplicant *wpa_s = user_data;
   3085 	dbus_bool_t fast_reauth;
   3086 
   3087 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
   3088 					      &fast_reauth))
   3089 		return FALSE;
   3090 
   3091 	wpa_s->conf->fast_reauth = fast_reauth;
   3092 	return TRUE;
   3093 }
   3094 
   3095 
   3096 /**
   3097  * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect
   3098  * @iter: Pointer to incoming dbus message iter
   3099  * @error: Location to store error on failure
   3100  * @user_data: Function specific data
   3101  * Returns: TRUE on success, FALSE on failure
   3102  *
   3103  * Getter for "DisconnectReason" property.  The reason is negative if it is
   3104  * locally generated.
   3105  */
   3106 dbus_bool_t wpas_dbus_getter_disconnect_reason(
   3107 	const struct wpa_dbus_property_desc *property_desc,
   3108 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3109 {
   3110 	struct wpa_supplicant *wpa_s = user_data;
   3111 	dbus_int32_t reason = wpa_s->disconnect_reason;
   3112 
   3113 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
   3114 						&reason, error);
   3115 }
   3116 
   3117 
   3118 /**
   3119  * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
   3120  * @iter: Pointer to incoming dbus message iter
   3121  * @error: Location to store error on failure
   3122  * @user_data: Function specific data
   3123  * Returns: TRUE on success, FALSE on failure
   3124  *
   3125  * Getter for "AssocStatusCode" property.
   3126  */
   3127 dbus_bool_t wpas_dbus_getter_assoc_status_code(
   3128 	const struct wpa_dbus_property_desc *property_desc,
   3129 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3130 {
   3131 	struct wpa_supplicant *wpa_s = user_data;
   3132 	dbus_int32_t status_code = wpa_s->assoc_status_code;
   3133 
   3134 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
   3135 						&status_code, error);
   3136 }
   3137 
   3138 
   3139 /**
   3140  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
   3141  * @iter: Pointer to incoming dbus message iter
   3142  * @error: Location to store error on failure
   3143  * @user_data: Function specific data
   3144  * Returns: TRUE on success, FALSE on failure
   3145  *
   3146  * Getter function for "BSSExpireAge" property.
   3147  */
   3148 dbus_bool_t wpas_dbus_getter_bss_expire_age(
   3149 	const struct wpa_dbus_property_desc *property_desc,
   3150 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3151 {
   3152 	struct wpa_supplicant *wpa_s = user_data;
   3153 	dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
   3154 
   3155 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
   3156 						&expire_age, error);
   3157 }
   3158 
   3159 
   3160 /**
   3161  * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
   3162  * @iter: Pointer to incoming dbus message iter
   3163  * @error: Location to store error on failure
   3164  * @user_data: Function specific data
   3165  * Returns: TRUE on success, FALSE on failure
   3166  *
   3167  * Setter function for "BSSExpireAge" property.
   3168  */
   3169 dbus_bool_t wpas_dbus_setter_bss_expire_age(
   3170 	const struct wpa_dbus_property_desc *property_desc,
   3171 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3172 {
   3173 	struct wpa_supplicant *wpa_s = user_data;
   3174 	dbus_uint32_t expire_age;
   3175 
   3176 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
   3177 					      &expire_age))
   3178 		return FALSE;
   3179 
   3180 	if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
   3181 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3182 				     "BSSExpireAge must be >= 10");
   3183 		return FALSE;
   3184 	}
   3185 	return TRUE;
   3186 }
   3187 
   3188 
   3189 /**
   3190  * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
   3191  * @iter: Pointer to incoming dbus message iter
   3192  * @error: Location to store error on failure
   3193  * @user_data: Function specific data
   3194  * Returns: TRUE on success, FALSE on failure
   3195  *
   3196  * Getter function for "BSSExpireCount" property.
   3197  */
   3198 dbus_bool_t wpas_dbus_getter_bss_expire_count(
   3199 	const struct wpa_dbus_property_desc *property_desc,
   3200 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3201 {
   3202 	struct wpa_supplicant *wpa_s = user_data;
   3203 	dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
   3204 
   3205 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
   3206 						&expire_count, error);
   3207 }
   3208 
   3209 
   3210 /**
   3211  * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
   3212  * @iter: Pointer to incoming dbus message iter
   3213  * @error: Location to store error on failure
   3214  * @user_data: Function specific data
   3215  * Returns: TRUE on success, FALSE on failure
   3216  *
   3217  * Setter function for "BSSExpireCount" property.
   3218  */
   3219 dbus_bool_t wpas_dbus_setter_bss_expire_count(
   3220 	const struct wpa_dbus_property_desc *property_desc,
   3221 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3222 {
   3223 	struct wpa_supplicant *wpa_s = user_data;
   3224 	dbus_uint32_t expire_count;
   3225 
   3226 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
   3227 					      &expire_count))
   3228 		return FALSE;
   3229 
   3230 	if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
   3231 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3232 				     "BSSExpireCount must be > 0");
   3233 		return FALSE;
   3234 	}
   3235 	return TRUE;
   3236 }
   3237 
   3238 
   3239 /**
   3240  * wpas_dbus_getter_country - Control country code
   3241  * @iter: Pointer to incoming dbus message iter
   3242  * @error: Location to store error on failure
   3243  * @user_data: Function specific data
   3244  * Returns: TRUE on success, FALSE on failure
   3245  *
   3246  * Getter function for "Country" property.
   3247  */
   3248 dbus_bool_t wpas_dbus_getter_country(
   3249 	const struct wpa_dbus_property_desc *property_desc,
   3250 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3251 {
   3252 	struct wpa_supplicant *wpa_s = user_data;
   3253 	char country[3];
   3254 	char *str = country;
   3255 
   3256 	country[0] = wpa_s->conf->country[0];
   3257 	country[1] = wpa_s->conf->country[1];
   3258 	country[2] = '\0';
   3259 
   3260 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
   3261 						&str, error);
   3262 }
   3263 
   3264 
   3265 /**
   3266  * wpas_dbus_setter_country - Control country code
   3267  * @iter: Pointer to incoming dbus message iter
   3268  * @error: Location to store error on failure
   3269  * @user_data: Function specific data
   3270  * Returns: TRUE on success, FALSE on failure
   3271  *
   3272  * Setter function for "Country" property.
   3273  */
   3274 dbus_bool_t wpas_dbus_setter_country(
   3275 	const struct wpa_dbus_property_desc *property_desc,
   3276 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3277 {
   3278 	struct wpa_supplicant *wpa_s = user_data;
   3279 	const char *country;
   3280 
   3281 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
   3282 					      &country))
   3283 		return FALSE;
   3284 
   3285 	if (!country[0] || !country[1]) {
   3286 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3287 				     "invalid country code");
   3288 		return FALSE;
   3289 	}
   3290 
   3291 	if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
   3292 		wpa_printf(MSG_DEBUG, "Failed to set country");
   3293 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3294 				     "failed to set country code");
   3295 		return FALSE;
   3296 	}
   3297 
   3298 	wpa_s->conf->country[0] = country[0];
   3299 	wpa_s->conf->country[1] = country[1];
   3300 	return TRUE;
   3301 }
   3302 
   3303 
   3304 /**
   3305  * wpas_dbus_getter_scan_interval - Get scan interval
   3306  * @iter: Pointer to incoming dbus message iter
   3307  * @error: Location to store error on failure
   3308  * @user_data: Function specific data
   3309  * Returns: TRUE on success, FALSE on failure
   3310  *
   3311  * Getter function for "ScanInterval" property.
   3312  */
   3313 dbus_bool_t wpas_dbus_getter_scan_interval(
   3314 	const struct wpa_dbus_property_desc *property_desc,
   3315 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3316 {
   3317 	struct wpa_supplicant *wpa_s = user_data;
   3318 	dbus_int32_t scan_interval = wpa_s->scan_interval;
   3319 
   3320 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
   3321 						&scan_interval, error);
   3322 }
   3323 
   3324 
   3325 /**
   3326  * wpas_dbus_setter_scan_interval - Control scan interval
   3327  * @iter: Pointer to incoming dbus message iter
   3328  * @error: Location to store error on failure
   3329  * @user_data: Function specific data
   3330  * Returns: TRUE on success, FALSE on failure
   3331  *
   3332  * Setter function for "ScanInterval" property.
   3333  */
   3334 dbus_bool_t wpas_dbus_setter_scan_interval(
   3335 	const struct wpa_dbus_property_desc *property_desc,
   3336 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3337 {
   3338 	struct wpa_supplicant *wpa_s = user_data;
   3339 	dbus_int32_t scan_interval;
   3340 
   3341 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32,
   3342 					      &scan_interval))
   3343 		return FALSE;
   3344 
   3345 	if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) {
   3346 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   3347 				     "scan_interval must be >= 0");
   3348 		return FALSE;
   3349 	}
   3350 	return TRUE;
   3351 }
   3352 
   3353 
   3354 /**
   3355  * wpas_dbus_getter_ifname - Get interface name
   3356  * @iter: Pointer to incoming dbus message iter
   3357  * @error: Location to store error on failure
   3358  * @user_data: Function specific data
   3359  * Returns: TRUE on success, FALSE on failure
   3360  *
   3361  * Getter for "Ifname" property.
   3362  */
   3363 dbus_bool_t wpas_dbus_getter_ifname(
   3364 	const struct wpa_dbus_property_desc *property_desc,
   3365 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3366 {
   3367 	struct wpa_supplicant *wpa_s = user_data;
   3368 
   3369 	return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error);
   3370 }
   3371 
   3372 
   3373 /**
   3374  * wpas_dbus_getter_driver - Get interface name
   3375  * @iter: Pointer to incoming dbus message iter
   3376  * @error: Location to store error on failure
   3377  * @user_data: Function specific data
   3378  * Returns: TRUE on success, FALSE on failure
   3379  *
   3380  * Getter for "Driver" property.
   3381  */
   3382 dbus_bool_t wpas_dbus_getter_driver(
   3383 	const struct wpa_dbus_property_desc *property_desc,
   3384 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3385 {
   3386 	struct wpa_supplicant *wpa_s = user_data;
   3387 
   3388 	if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
   3389 		wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set",
   3390 			   __func__);
   3391 		dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set",
   3392 			       __func__);
   3393 		return FALSE;
   3394 	}
   3395 
   3396 	return wpas_dbus_string_property_getter(iter, wpa_s->driver->name,
   3397 						error);
   3398 }
   3399 
   3400 
   3401 /**
   3402  * wpas_dbus_getter_current_bss - Get current bss object path
   3403  * @iter: Pointer to incoming dbus message iter
   3404  * @error: Location to store error on failure
   3405  * @user_data: Function specific data
   3406  * Returns: TRUE on success, FALSE on failure
   3407  *
   3408  * Getter for "CurrentBSS" property.
   3409  */
   3410 dbus_bool_t wpas_dbus_getter_current_bss(
   3411 	const struct wpa_dbus_property_desc *property_desc,
   3412 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3413 {
   3414 	struct wpa_supplicant *wpa_s = user_data;
   3415 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
   3416 
   3417 	if (wpa_s->current_bss && wpa_s->dbus_new_path)
   3418 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3419 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   3420 			    wpa_s->dbus_new_path, wpa_s->current_bss->id);
   3421 	else
   3422 		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
   3423 
   3424 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
   3425 						&bss_obj_path, error);
   3426 }
   3427 
   3428 
   3429 /**
   3430  * wpas_dbus_getter_current_network - Get current network object path
   3431  * @iter: Pointer to incoming dbus message iter
   3432  * @error: Location to store error on failure
   3433  * @user_data: Function specific data
   3434  * Returns: TRUE on success, FALSE on failure
   3435  *
   3436  * Getter for "CurrentNetwork" property.
   3437  */
   3438 dbus_bool_t wpas_dbus_getter_current_network(
   3439 	const struct wpa_dbus_property_desc *property_desc,
   3440 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3441 {
   3442 	struct wpa_supplicant *wpa_s = user_data;
   3443 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
   3444 
   3445 	if (wpa_s->current_ssid && wpa_s->dbus_new_path)
   3446 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3447 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
   3448 			    wpa_s->dbus_new_path, wpa_s->current_ssid->id);
   3449 	else
   3450 		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
   3451 
   3452 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
   3453 						&net_obj_path, error);
   3454 }
   3455 
   3456 
   3457 /**
   3458  * wpas_dbus_getter_current_auth_mode - Get current authentication type
   3459  * @iter: Pointer to incoming dbus message iter
   3460  * @error: Location to store error on failure
   3461  * @user_data: Function specific data
   3462  * Returns: TRUE on success, FALSE on failure
   3463  *
   3464  * Getter for "CurrentAuthMode" property.
   3465  */
   3466 dbus_bool_t wpas_dbus_getter_current_auth_mode(
   3467 	const struct wpa_dbus_property_desc *property_desc,
   3468 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3469 {
   3470 	struct wpa_supplicant *wpa_s = user_data;
   3471 	const char *eap_mode;
   3472 	const char *auth_mode;
   3473 	char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
   3474 
   3475 	if (wpa_s->wpa_state != WPA_COMPLETED) {
   3476 		auth_mode = "INACTIVE";
   3477 	} else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
   3478 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
   3479 		eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
   3480 		os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
   3481 			    "EAP-%s", eap_mode);
   3482 		auth_mode = eap_mode_buf;
   3483 
   3484 	} else if (wpa_s->current_ssid) {
   3485 		auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
   3486 					     wpa_s->current_ssid->proto);
   3487 	} else {
   3488 		auth_mode = "UNKNOWN";
   3489 	}
   3490 
   3491 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
   3492 						&auth_mode, error);
   3493 }
   3494 
   3495 
   3496 /**
   3497  * wpas_dbus_getter_bridge_ifname - Get interface name
   3498  * @iter: Pointer to incoming dbus message iter
   3499  * @error: Location to store error on failure
   3500  * @user_data: Function specific data
   3501  * Returns: TRUE on success, FALSE on failure
   3502  *
   3503  * Getter for "BridgeIfname" property.
   3504  */
   3505 dbus_bool_t wpas_dbus_getter_bridge_ifname(
   3506 	const struct wpa_dbus_property_desc *property_desc,
   3507 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3508 {
   3509 	struct wpa_supplicant *wpa_s = user_data;
   3510 
   3511 	return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname,
   3512 						error);
   3513 }
   3514 
   3515 
   3516 /**
   3517  * wpas_dbus_getter_config_file - Get interface configuration file path
   3518  * @iter: Pointer to incoming dbus message iter
   3519  * @error: Location to store error on failure
   3520  * @user_data: Function specific data
   3521  * Returns: TRUE on success, FALSE on failure
   3522  *
   3523  * Getter for "ConfigFile" property.
   3524  */
   3525 dbus_bool_t wpas_dbus_getter_config_file(
   3526 	const struct wpa_dbus_property_desc *property_desc,
   3527 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3528 {
   3529 	struct wpa_supplicant *wpa_s = user_data;
   3530 
   3531 	return wpas_dbus_string_property_getter(iter, wpa_s->confname, error);
   3532 }
   3533 
   3534 
   3535 /**
   3536  * wpas_dbus_getter_bsss - Get array of BSSs objects
   3537  * @iter: Pointer to incoming dbus message iter
   3538  * @error: Location to store error on failure
   3539  * @user_data: Function specific data
   3540  * Returns: TRUE on success, FALSE on failure
   3541  *
   3542  * Getter for "BSSs" property.
   3543  */
   3544 dbus_bool_t wpas_dbus_getter_bsss(
   3545 	const struct wpa_dbus_property_desc *property_desc,
   3546 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3547 {
   3548 	struct wpa_supplicant *wpa_s = user_data;
   3549 	struct wpa_bss *bss;
   3550 	char **paths;
   3551 	unsigned int i = 0;
   3552 	dbus_bool_t success = FALSE;
   3553 
   3554 	if (!wpa_s->dbus_new_path) {
   3555 		dbus_set_error(error, DBUS_ERROR_FAILED,
   3556 			       "%s: no D-Bus interface", __func__);
   3557 		return FALSE;
   3558 	}
   3559 
   3560 	paths = os_calloc(wpa_s->num_bss, sizeof(char *));
   3561 	if (!paths) {
   3562 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   3563 		return FALSE;
   3564 	}
   3565 
   3566 	/* Loop through scan results and append each result's object path */
   3567 	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
   3568 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   3569 		if (paths[i] == NULL) {
   3570 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
   3571 					     "no memory");
   3572 			goto out;
   3573 		}
   3574 		/* Construct the object path for this BSS. */
   3575 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
   3576 			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   3577 			    wpa_s->dbus_new_path, bss->id);
   3578 	}
   3579 
   3580 	success = wpas_dbus_simple_array_property_getter(iter,
   3581 							 DBUS_TYPE_OBJECT_PATH,
   3582 							 paths, wpa_s->num_bss,
   3583 							 error);
   3584 
   3585 out:
   3586 	while (i)
   3587 		os_free(paths[--i]);
   3588 	os_free(paths);
   3589 	return success;
   3590 }
   3591 
   3592 
   3593 /**
   3594  * wpas_dbus_getter_networks - Get array of networks objects
   3595  * @iter: Pointer to incoming dbus message iter
   3596  * @error: Location to store error on failure
   3597  * @user_data: Function specific data
   3598  * Returns: TRUE on success, FALSE on failure
   3599  *
   3600  * Getter for "Networks" property.
   3601  */
   3602 dbus_bool_t wpas_dbus_getter_networks(
   3603 	const struct wpa_dbus_property_desc *property_desc,
   3604 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3605 {
   3606 	struct wpa_supplicant *wpa_s = user_data;
   3607 	struct wpa_ssid *ssid;
   3608 	char **paths;
   3609 	unsigned int i = 0, num = 0;
   3610 	dbus_bool_t success = FALSE;
   3611 
   3612 	if (!wpa_s->dbus_new_path) {
   3613 		dbus_set_error(error, DBUS_ERROR_FAILED,
   3614 			       "%s: no D-Bus interface", __func__);
   3615 		return FALSE;
   3616 	}
   3617 
   3618 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
   3619 		if (!network_is_persistent_group(ssid))
   3620 			num++;
   3621 
   3622 	paths = os_calloc(num, sizeof(char *));
   3623 	if (!paths) {
   3624 		dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory");
   3625 		return FALSE;
   3626 	}
   3627 
   3628 	/* Loop through configured networks and append object path of each */
   3629 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
   3630 		if (network_is_persistent_group(ssid))
   3631 			continue;
   3632 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   3633 		if (paths[i] == NULL) {
   3634 			dbus_set_error(error, DBUS_ERROR_NO_MEMORY,
   3635 				       "no memory");
   3636 			goto out;
   3637 		}
   3638 
   3639 		/* Construct the object path for this network. */
   3640 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
   3641 			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
   3642 			    wpa_s->dbus_new_path, ssid->id);
   3643 	}
   3644 
   3645 	success = wpas_dbus_simple_array_property_getter(iter,
   3646 							 DBUS_TYPE_OBJECT_PATH,
   3647 							 paths, num, error);
   3648 
   3649 out:
   3650 	while (i)
   3651 		os_free(paths[--i]);
   3652 	os_free(paths);
   3653 	return success;
   3654 }
   3655 
   3656 
   3657 /**
   3658  * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path
   3659  * @iter: Pointer to incoming dbus message iter
   3660  * @error: Location to store error on failure
   3661  * @user_data: Function specific data
   3662  * Returns: A dbus message containing the PKCS #11 engine path
   3663  *
   3664  * Getter for "PKCS11EnginePath" property.
   3665  */
   3666 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
   3667 	const struct wpa_dbus_property_desc *property_desc,
   3668 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3669 {
   3670 	struct wpa_supplicant *wpa_s = user_data;
   3671 
   3672 	return wpas_dbus_string_property_getter(iter,
   3673 						wpa_s->conf->pkcs11_engine_path,
   3674 						error);
   3675 }
   3676 
   3677 
   3678 /**
   3679  * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path
   3680  * @iter: Pointer to incoming dbus message iter
   3681  * @error: Location to store error on failure
   3682  * @user_data: Function specific data
   3683  * Returns: A dbus message containing the PKCS #11 module path
   3684  *
   3685  * Getter for "PKCS11ModulePath" property.
   3686  */
   3687 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
   3688 	const struct wpa_dbus_property_desc *property_desc,
   3689 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3690 {
   3691 	struct wpa_supplicant *wpa_s = user_data;
   3692 
   3693 	return wpas_dbus_string_property_getter(iter,
   3694 						wpa_s->conf->pkcs11_module_path,
   3695 						error);
   3696 }
   3697 
   3698 
   3699 /**
   3700  * wpas_dbus_getter_blobs - Get all blobs defined for this interface
   3701  * @iter: Pointer to incoming dbus message iter
   3702  * @error: Location to store error on failure
   3703  * @user_data: Function specific data
   3704  * Returns: TRUE on success, FALSE on failure
   3705  *
   3706  * Getter for "Blobs" property.
   3707  */
   3708 dbus_bool_t wpas_dbus_getter_blobs(
   3709 	const struct wpa_dbus_property_desc *property_desc,
   3710 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3711 {
   3712 	struct wpa_supplicant *wpa_s = user_data;
   3713 	DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
   3714 	struct wpa_config_blob *blob;
   3715 
   3716 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   3717 					      "a{say}", &variant_iter) ||
   3718 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
   3719 					      "{say}", &dict_iter)) {
   3720 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   3721 		return FALSE;
   3722 	}
   3723 
   3724 	blob = wpa_s->conf->blobs;
   3725 	while (blob) {
   3726 		if (!dbus_message_iter_open_container(&dict_iter,
   3727 						      DBUS_TYPE_DICT_ENTRY,
   3728 						      NULL, &entry_iter) ||
   3729 		    !dbus_message_iter_append_basic(&entry_iter,
   3730 						    DBUS_TYPE_STRING,
   3731 						    &(blob->name)) ||
   3732 		    !dbus_message_iter_open_container(&entry_iter,
   3733 						      DBUS_TYPE_ARRAY,
   3734 						      DBUS_TYPE_BYTE_AS_STRING,
   3735 						      &array_iter) ||
   3736 		    !dbus_message_iter_append_fixed_array(&array_iter,
   3737 							  DBUS_TYPE_BYTE,
   3738 							  &(blob->data),
   3739 							  blob->len) ||
   3740 		    !dbus_message_iter_close_container(&entry_iter,
   3741 						       &array_iter) ||
   3742 		    !dbus_message_iter_close_container(&dict_iter,
   3743 						       &entry_iter)) {
   3744 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
   3745 					     "no memory");
   3746 			return FALSE;
   3747 		}
   3748 
   3749 		blob = blob->next;
   3750 	}
   3751 
   3752 	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
   3753 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
   3754 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   3755 		return FALSE;
   3756 	}
   3757 
   3758 	return TRUE;
   3759 }
   3760 
   3761 
   3762 dbus_bool_t wpas_dbus_getter_iface_global(
   3763 	const struct wpa_dbus_property_desc *property_desc,
   3764 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3765 {
   3766 	struct wpa_supplicant *wpa_s = user_data;
   3767 	int ret;
   3768 	char buf[250];
   3769 	char *p = buf;
   3770 
   3771 	if (!property_desc->data) {
   3772 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
   3773 			       "Unhandled interface property %s",
   3774 			       property_desc->dbus_property);
   3775 		return FALSE;
   3776 	}
   3777 
   3778 	ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
   3779 				   sizeof(buf));
   3780 	if (ret < 0)
   3781 		*p = '\0';
   3782 
   3783 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
   3784 						error);
   3785 }
   3786 
   3787 
   3788 dbus_bool_t wpas_dbus_setter_iface_global(
   3789 	const struct wpa_dbus_property_desc *property_desc,
   3790 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3791 {
   3792 	struct wpa_supplicant *wpa_s = user_data;
   3793 	const char *new_value = NULL;
   3794 	char buf[250];
   3795 	size_t combined_len;
   3796 	int ret;
   3797 
   3798 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
   3799 					      &new_value))
   3800 		return FALSE;
   3801 
   3802 	combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
   3803 		3;
   3804 	if (combined_len >= sizeof(buf)) {
   3805 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
   3806 			       "Interface property %s value too large",
   3807 			       property_desc->dbus_property);
   3808 		return FALSE;
   3809 	}
   3810 
   3811 	if (!new_value[0])
   3812 		new_value = "NULL";
   3813 
   3814 	ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
   3815 			  new_value);
   3816 	if (os_snprintf_error(combined_len, ret)) {
   3817 		dbus_set_error(error,  WPAS_DBUS_ERROR_UNKNOWN_ERROR,
   3818 			       "Failed to construct new interface property %s",
   3819 			       property_desc->dbus_property);
   3820 		return FALSE;
   3821 	}
   3822 
   3823 	if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
   3824 		dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
   3825 			       "Failed to set interface property %s",
   3826 			       property_desc->dbus_property);
   3827 		return FALSE;
   3828 	}
   3829 
   3830 	wpa_supplicant_update_config(wpa_s);
   3831 	return TRUE;
   3832 }
   3833 
   3834 
   3835 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
   3836 				       DBusError *error, const char *func_name)
   3837 {
   3838 	struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id);
   3839 
   3840 	if (!res) {
   3841 		wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found",
   3842 			   func_name, args->id);
   3843 		dbus_set_error(error, DBUS_ERROR_FAILED,
   3844 			       "%s: BSS %d not found",
   3845 			       func_name, args->id);
   3846 	}
   3847 
   3848 	return res;
   3849 }
   3850 
   3851 
   3852 /**
   3853  * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
   3854  * @iter: Pointer to incoming dbus message iter
   3855  * @error: Location to store error on failure
   3856  * @user_data: Function specific data
   3857  * Returns: TRUE on success, FALSE on failure
   3858  *
   3859  * Getter for "BSSID" property.
   3860  */
   3861 dbus_bool_t wpas_dbus_getter_bss_bssid(
   3862 	const struct wpa_dbus_property_desc *property_desc,
   3863 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3864 {
   3865 	struct bss_handler_args *args = user_data;
   3866 	struct wpa_bss *res;
   3867 
   3868 	res = get_bss_helper(args, error, __func__);
   3869 	if (!res)
   3870 		return FALSE;
   3871 
   3872 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   3873 						      res->bssid, ETH_ALEN,
   3874 						      error);
   3875 }
   3876 
   3877 
   3878 /**
   3879  * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
   3880  * @iter: Pointer to incoming dbus message iter
   3881  * @error: Location to store error on failure
   3882  * @user_data: Function specific data
   3883  * Returns: TRUE on success, FALSE on failure
   3884  *
   3885  * Getter for "SSID" property.
   3886  */
   3887 dbus_bool_t wpas_dbus_getter_bss_ssid(
   3888 	const struct wpa_dbus_property_desc *property_desc,
   3889 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3890 {
   3891 	struct bss_handler_args *args = user_data;
   3892 	struct wpa_bss *res;
   3893 
   3894 	res = get_bss_helper(args, error, __func__);
   3895 	if (!res)
   3896 		return FALSE;
   3897 
   3898 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   3899 						      res->ssid, res->ssid_len,
   3900 						      error);
   3901 }
   3902 
   3903 
   3904 /**
   3905  * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
   3906  * @iter: Pointer to incoming dbus message iter
   3907  * @error: Location to store error on failure
   3908  * @user_data: Function specific data
   3909  * Returns: TRUE on success, FALSE on failure
   3910  *
   3911  * Getter for "Privacy" property.
   3912  */
   3913 dbus_bool_t wpas_dbus_getter_bss_privacy(
   3914 	const struct wpa_dbus_property_desc *property_desc,
   3915 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3916 {
   3917 	struct bss_handler_args *args = user_data;
   3918 	struct wpa_bss *res;
   3919 	dbus_bool_t privacy;
   3920 
   3921 	res = get_bss_helper(args, error, __func__);
   3922 	if (!res)
   3923 		return FALSE;
   3924 
   3925 	privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
   3926 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
   3927 						&privacy, error);
   3928 }
   3929 
   3930 
   3931 /**
   3932  * wpas_dbus_getter_bss_mode - Return the mode of a BSS
   3933  * @iter: Pointer to incoming dbus message iter
   3934  * @error: Location to store error on failure
   3935  * @user_data: Function specific data
   3936  * Returns: TRUE on success, FALSE on failure
   3937  *
   3938  * Getter for "Mode" property.
   3939  */
   3940 dbus_bool_t wpas_dbus_getter_bss_mode(
   3941 	const struct wpa_dbus_property_desc *property_desc,
   3942 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3943 {
   3944 	struct bss_handler_args *args = user_data;
   3945 	struct wpa_bss *res;
   3946 	const char *mode;
   3947 	const u8 *mesh;
   3948 
   3949 	res = get_bss_helper(args, error, __func__);
   3950 	if (!res)
   3951 		return FALSE;
   3952 	if (bss_is_dmg(res)) {
   3953 		switch (res->caps & IEEE80211_CAP_DMG_MASK) {
   3954 		case IEEE80211_CAP_DMG_PBSS:
   3955 		case IEEE80211_CAP_DMG_IBSS:
   3956 			mode = "ad-hoc";
   3957 			break;
   3958 		case IEEE80211_CAP_DMG_AP:
   3959 			mode = "infrastructure";
   3960 			break;
   3961 		default:
   3962 			mode = "";
   3963 			break;
   3964 		}
   3965 	} else {
   3966 		mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID);
   3967 		if (mesh)
   3968 			mode = "mesh";
   3969 		else if (res->caps & IEEE80211_CAP_IBSS)
   3970 			mode = "ad-hoc";
   3971 		else
   3972 			mode = "infrastructure";
   3973 	}
   3974 
   3975 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
   3976 						&mode, error);
   3977 }
   3978 
   3979 
   3980 /**
   3981  * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
   3982  * @iter: Pointer to incoming dbus message iter
   3983  * @error: Location to store error on failure
   3984  * @user_data: Function specific data
   3985  * Returns: TRUE on success, FALSE on failure
   3986  *
   3987  * Getter for "Level" property.
   3988  */
   3989 dbus_bool_t wpas_dbus_getter_bss_signal(
   3990 	const struct wpa_dbus_property_desc *property_desc,
   3991 	DBusMessageIter *iter, DBusError *error, void *user_data)
   3992 {
   3993 	struct bss_handler_args *args = user_data;
   3994 	struct wpa_bss *res;
   3995 	s16 level;
   3996 
   3997 	res = get_bss_helper(args, error, __func__);
   3998 	if (!res)
   3999 		return FALSE;
   4000 
   4001 	level = (s16) res->level;
   4002 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16,
   4003 						&level, error);
   4004 }
   4005 
   4006 
   4007 /**
   4008  * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
   4009  * @iter: Pointer to incoming dbus message iter
   4010  * @error: Location to store error on failure
   4011  * @user_data: Function specific data
   4012  * Returns: TRUE on success, FALSE on failure
   4013  *
   4014  * Getter for "Frequency" property.
   4015  */
   4016 dbus_bool_t wpas_dbus_getter_bss_frequency(
   4017 	const struct wpa_dbus_property_desc *property_desc,
   4018 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4019 {
   4020 	struct bss_handler_args *args = user_data;
   4021 	struct wpa_bss *res;
   4022 	u16 freq;
   4023 
   4024 	res = get_bss_helper(args, error, __func__);
   4025 	if (!res)
   4026 		return FALSE;
   4027 
   4028 	freq = (u16) res->freq;
   4029 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
   4030 						&freq, error);
   4031 }
   4032 
   4033 
   4034 static int cmp_u8s_desc(const void *a, const void *b)
   4035 {
   4036 	return (*(u8 *) b - *(u8 *) a);
   4037 }
   4038 
   4039 
   4040 /**
   4041  * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
   4042  * @iter: Pointer to incoming dbus message iter
   4043  * @error: Location to store error on failure
   4044  * @user_data: Function specific data
   4045  * Returns: TRUE on success, FALSE on failure
   4046  *
   4047  * Getter for "Rates" property.
   4048  */
   4049 dbus_bool_t wpas_dbus_getter_bss_rates(
   4050 	const struct wpa_dbus_property_desc *property_desc,
   4051 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4052 {
   4053 	struct bss_handler_args *args = user_data;
   4054 	struct wpa_bss *res;
   4055 	u8 *ie_rates = NULL;
   4056 	u32 *real_rates;
   4057 	int rates_num, i;
   4058 	dbus_bool_t success = FALSE;
   4059 
   4060 	res = get_bss_helper(args, error, __func__);
   4061 	if (!res)
   4062 		return FALSE;
   4063 
   4064 	rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
   4065 	if (rates_num < 0)
   4066 		return FALSE;
   4067 
   4068 	qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
   4069 
   4070 	real_rates = os_malloc(sizeof(u32) * rates_num);
   4071 	if (!real_rates) {
   4072 		os_free(ie_rates);
   4073 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4074 		return FALSE;
   4075 	}
   4076 
   4077 	for (i = 0; i < rates_num; i++)
   4078 		real_rates[i] = ie_rates[i] * 500000;
   4079 
   4080 	success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32,
   4081 							 real_rates, rates_num,
   4082 							 error);
   4083 
   4084 	os_free(ie_rates);
   4085 	os_free(real_rates);
   4086 	return success;
   4087 }
   4088 
   4089 
   4090 static dbus_bool_t wpas_dbus_get_bss_security_prop(
   4091 	const struct wpa_dbus_property_desc *property_desc,
   4092 	DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
   4093 {
   4094 	DBusMessageIter iter_dict, variant_iter;
   4095 	const char *group;
   4096 	const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
   4097 	const char *key_mgmt[9]; /* max 9 key managements may be supported */
   4098 	int n;
   4099 
   4100 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   4101 					      "a{sv}", &variant_iter))
   4102 		goto nomem;
   4103 
   4104 	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
   4105 		goto nomem;
   4106 
   4107 	/* KeyMgmt */
   4108 	n = 0;
   4109 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
   4110 		key_mgmt[n++] = "wpa-psk";
   4111 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
   4112 		key_mgmt[n++] = "wpa-ft-psk";
   4113 	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
   4114 		key_mgmt[n++] = "wpa-psk-sha256";
   4115 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
   4116 		key_mgmt[n++] = "wpa-eap";
   4117 	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
   4118 		key_mgmt[n++] = "wpa-ft-eap";
   4119 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
   4120 		key_mgmt[n++] = "wpa-eap-sha256";
   4121 #ifdef CONFIG_SUITEB
   4122 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
   4123 		key_mgmt[n++] = "wpa-eap-suite-b";
   4124 #endif /* CONFIG_SUITEB */
   4125 #ifdef CONFIG_SUITEB192
   4126 	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
   4127 		key_mgmt[n++] = "wpa-eap-suite-b-192";
   4128 #endif /* CONFIG_SUITEB192 */
   4129 	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
   4130 		key_mgmt[n++] = "wpa-none";
   4131 
   4132 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
   4133 					       key_mgmt, n))
   4134 		goto nomem;
   4135 
   4136 	/* Group */
   4137 	switch (ie_data->group_cipher) {
   4138 	case WPA_CIPHER_WEP40:
   4139 		group = "wep40";
   4140 		break;
   4141 	case WPA_CIPHER_TKIP:
   4142 		group = "tkip";
   4143 		break;
   4144 	case WPA_CIPHER_CCMP:
   4145 		group = "ccmp";
   4146 		break;
   4147 	case WPA_CIPHER_GCMP:
   4148 		group = "gcmp";
   4149 		break;
   4150 	case WPA_CIPHER_WEP104:
   4151 		group = "wep104";
   4152 		break;
   4153 	case WPA_CIPHER_CCMP_256:
   4154 		group = "ccmp-256";
   4155 		break;
   4156 	case WPA_CIPHER_GCMP_256:
   4157 		group = "gcmp-256";
   4158 		break;
   4159 	default:
   4160 		group = "";
   4161 		break;
   4162 	}
   4163 
   4164 	if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
   4165 		goto nomem;
   4166 
   4167 	/* Pairwise */
   4168 	n = 0;
   4169 	if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
   4170 		pairwise[n++] = "tkip";
   4171 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
   4172 		pairwise[n++] = "ccmp";
   4173 	if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
   4174 		pairwise[n++] = "gcmp";
   4175 	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
   4176 		pairwise[n++] = "ccmp-256";
   4177 	if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
   4178 		pairwise[n++] = "gcmp-256";
   4179 
   4180 	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
   4181 					       pairwise, n))
   4182 		goto nomem;
   4183 
   4184 	/* Management group (RSN only) */
   4185 	if (ie_data->proto == WPA_PROTO_RSN) {
   4186 		switch (ie_data->mgmt_group_cipher) {
   4187 #ifdef CONFIG_IEEE80211W
   4188 		case WPA_CIPHER_AES_128_CMAC:
   4189 			group = "aes128cmac";
   4190 			break;
   4191 #endif /* CONFIG_IEEE80211W */
   4192 		default:
   4193 			group = "";
   4194 			break;
   4195 		}
   4196 
   4197 		if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
   4198 						 group))
   4199 			goto nomem;
   4200 	}
   4201 
   4202 	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
   4203 	    !dbus_message_iter_close_container(iter, &variant_iter))
   4204 		goto nomem;
   4205 
   4206 	return TRUE;
   4207 
   4208 nomem:
   4209 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4210 	return FALSE;
   4211 }
   4212 
   4213 
   4214 /**
   4215  * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
   4216  * @iter: Pointer to incoming dbus message iter
   4217  * @error: Location to store error on failure
   4218  * @user_data: Function specific data
   4219  * Returns: TRUE on success, FALSE on failure
   4220  *
   4221  * Getter for "WPA" property.
   4222  */
   4223 dbus_bool_t wpas_dbus_getter_bss_wpa(
   4224 	const struct wpa_dbus_property_desc *property_desc,
   4225 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4226 {
   4227 	struct bss_handler_args *args = user_data;
   4228 	struct wpa_bss *res;
   4229 	struct wpa_ie_data wpa_data;
   4230 	const u8 *ie;
   4231 
   4232 	res = get_bss_helper(args, error, __func__);
   4233 	if (!res)
   4234 		return FALSE;
   4235 
   4236 	os_memset(&wpa_data, 0, sizeof(wpa_data));
   4237 	ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
   4238 	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
   4239 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   4240 				     "failed to parse WPA IE");
   4241 		return FALSE;
   4242 	}
   4243 
   4244 	return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
   4245 }
   4246 
   4247 
   4248 /**
   4249  * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
   4250  * @iter: Pointer to incoming dbus message iter
   4251  * @error: Location to store error on failure
   4252  * @user_data: Function specific data
   4253  * Returns: TRUE on success, FALSE on failure
   4254  *
   4255  * Getter for "RSN" property.
   4256  */
   4257 dbus_bool_t wpas_dbus_getter_bss_rsn(
   4258 	const struct wpa_dbus_property_desc *property_desc,
   4259 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4260 {
   4261 	struct bss_handler_args *args = user_data;
   4262 	struct wpa_bss *res;
   4263 	struct wpa_ie_data wpa_data;
   4264 	const u8 *ie;
   4265 
   4266 	res = get_bss_helper(args, error, __func__);
   4267 	if (!res)
   4268 		return FALSE;
   4269 
   4270 	os_memset(&wpa_data, 0, sizeof(wpa_data));
   4271 	ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
   4272 	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) {
   4273 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
   4274 				     "failed to parse RSN IE");
   4275 		return FALSE;
   4276 	}
   4277 
   4278 	return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
   4279 }
   4280 
   4281 
   4282 /**
   4283  * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS
   4284  * @iter: Pointer to incoming dbus message iter
   4285  * @error: Location to store error on failure
   4286  * @user_data: Function specific data
   4287  * Returns: TRUE on success, FALSE on failure
   4288  *
   4289  * Getter for "WPS" property.
   4290  */
   4291 dbus_bool_t wpas_dbus_getter_bss_wps(
   4292 	const struct wpa_dbus_property_desc *property_desc,
   4293 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4294 {
   4295 	struct bss_handler_args *args = user_data;
   4296 	struct wpa_bss *res;
   4297 #ifdef CONFIG_WPS
   4298 	struct wpabuf *wps_ie;
   4299 #endif /* CONFIG_WPS */
   4300 	DBusMessageIter iter_dict, variant_iter;
   4301 	int wps_support = 0;
   4302 	const char *type = "";
   4303 
   4304 	res = get_bss_helper(args, error, __func__);
   4305 	if (!res)
   4306 		return FALSE;
   4307 
   4308 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   4309 					      "a{sv}", &variant_iter) ||
   4310 	    !wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
   4311 		goto nomem;
   4312 
   4313 #ifdef CONFIG_WPS
   4314 	wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
   4315 	if (wps_ie) {
   4316 		wps_support = 1;
   4317 		if (wps_is_selected_pbc_registrar(wps_ie))
   4318 			type = "pbc";
   4319 		else if (wps_is_selected_pin_registrar(wps_ie))
   4320 			type = "pin";
   4321 
   4322 		wpabuf_free(wps_ie);
   4323 	}
   4324 #endif /* CONFIG_WPS */
   4325 
   4326 	if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
   4327 	    !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
   4328 	    !dbus_message_iter_close_container(iter, &variant_iter))
   4329 		goto nomem;
   4330 
   4331 	return TRUE;
   4332 
   4333 nomem:
   4334 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4335 	return FALSE;
   4336 }
   4337 
   4338 
   4339 /**
   4340  * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
   4341  * @iter: Pointer to incoming dbus message iter
   4342  * @error: Location to store error on failure
   4343  * @user_data: Function specific data
   4344  * Returns: TRUE on success, FALSE on failure
   4345  *
   4346  * Getter for "IEs" property.
   4347  */
   4348 dbus_bool_t wpas_dbus_getter_bss_ies(
   4349 	const struct wpa_dbus_property_desc *property_desc,
   4350 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4351 {
   4352 	struct bss_handler_args *args = user_data;
   4353 	struct wpa_bss *res;
   4354 
   4355 	res = get_bss_helper(args, error, __func__);
   4356 	if (!res)
   4357 		return FALSE;
   4358 
   4359 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   4360 						      res + 1, res->ie_len,
   4361 						      error);
   4362 }
   4363 
   4364 
   4365 /**
   4366  * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen
   4367  * @iter: Pointer to incoming dbus message iter
   4368  * @error: Location to store error on failure
   4369  * @user_data: Function specific data
   4370  * Returns: TRUE on success, FALSE on failure
   4371  *
   4372  * Getter for BSS age
   4373  */
   4374 dbus_bool_t wpas_dbus_getter_bss_age(
   4375 	const struct wpa_dbus_property_desc *property_desc,
   4376 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4377 {
   4378 	struct bss_handler_args *args = user_data;
   4379 	struct wpa_bss *res;
   4380 	struct os_reltime now, diff = { 0, 0 };
   4381 	u32 age;
   4382 
   4383 	res = get_bss_helper(args, error, __func__);
   4384 	if (!res)
   4385 		return FALSE;
   4386 
   4387 	os_get_reltime(&now);
   4388 	os_reltime_sub(&now, &res->last_update, &diff);
   4389 	age = diff.sec > 0 ? diff.sec : 0;
   4390 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age,
   4391 						error);
   4392 }
   4393 
   4394 
   4395 /**
   4396  * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
   4397  * @iter: Pointer to incoming dbus message iter
   4398  * @error: Location to store error on failure
   4399  * @user_data: Function specific data
   4400  * Returns: TRUE on success, FALSE on failure
   4401  *
   4402  * Getter for "enabled" property of a configured network.
   4403  */
   4404 dbus_bool_t wpas_dbus_getter_enabled(
   4405 	const struct wpa_dbus_property_desc *property_desc,
   4406 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4407 {
   4408 	struct network_handler_args *net = user_data;
   4409 	dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
   4410 
   4411 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
   4412 						&enabled, error);
   4413 }
   4414 
   4415 
   4416 /**
   4417  * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
   4418  * @iter: Pointer to incoming dbus message iter
   4419  * @error: Location to store error on failure
   4420  * @user_data: Function specific data
   4421  * Returns: TRUE on success, FALSE on failure
   4422  *
   4423  * Setter for "Enabled" property of a configured network.
   4424  */
   4425 dbus_bool_t wpas_dbus_setter_enabled(
   4426 	const struct wpa_dbus_property_desc *property_desc,
   4427 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4428 {
   4429 	struct network_handler_args *net = user_data;
   4430 	struct wpa_supplicant *wpa_s;
   4431 	struct wpa_ssid *ssid;
   4432 	dbus_bool_t enable;
   4433 
   4434 	if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
   4435 					      &enable))
   4436 		return FALSE;
   4437 
   4438 	wpa_s = net->wpa_s;
   4439 	ssid = net->ssid;
   4440 
   4441 	if (enable)
   4442 		wpa_supplicant_enable_network(wpa_s, ssid);
   4443 	else
   4444 		wpa_supplicant_disable_network(wpa_s, ssid);
   4445 
   4446 	return TRUE;
   4447 }
   4448 
   4449 
   4450 /**
   4451  * wpas_dbus_getter_network_properties - Get options for a configured network
   4452  * @iter: Pointer to incoming dbus message iter
   4453  * @error: Location to store error on failure
   4454  * @user_data: Function specific data
   4455  * Returns: TRUE on success, FALSE on failure
   4456  *
   4457  * Getter for "Properties" property of a configured network.
   4458  */
   4459 dbus_bool_t wpas_dbus_getter_network_properties(
   4460 	const struct wpa_dbus_property_desc *property_desc,
   4461 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4462 {
   4463 	struct network_handler_args *net = user_data;
   4464 	DBusMessageIter	variant_iter, dict_iter;
   4465 	char **iterator;
   4466 	char **props = wpa_config_get_all(net->ssid, 1);
   4467 	dbus_bool_t success = FALSE;
   4468 
   4469 	if (!props) {
   4470 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4471 		return FALSE;
   4472 	}
   4473 
   4474 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}",
   4475 					      &variant_iter) ||
   4476 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
   4477 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4478 		goto out;
   4479 	}
   4480 
   4481 	iterator = props;
   4482 	while (*iterator) {
   4483 		if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
   4484 						 *(iterator + 1))) {
   4485 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
   4486 					     "no memory");
   4487 			goto out;
   4488 		}
   4489 		iterator += 2;
   4490 	}
   4491 
   4492 
   4493 	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
   4494 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
   4495 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   4496 		goto out;
   4497 	}
   4498 
   4499 	success = TRUE;
   4500 
   4501 out:
   4502 	iterator = props;
   4503 	while (*iterator) {
   4504 		os_free(*iterator);
   4505 		iterator++;
   4506 	}
   4507 	os_free(props);
   4508 	return success;
   4509 }
   4510 
   4511 
   4512 /**
   4513  * wpas_dbus_setter_network_properties - Set options for a configured network
   4514  * @iter: Pointer to incoming dbus message iter
   4515  * @error: Location to store error on failure
   4516  * @user_data: Function specific data
   4517  * Returns: TRUE on success, FALSE on failure
   4518  *
   4519  * Setter for "Properties" property of a configured network.
   4520  */
   4521 dbus_bool_t wpas_dbus_setter_network_properties(
   4522 	const struct wpa_dbus_property_desc *property_desc,
   4523 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4524 {
   4525 	struct network_handler_args *net = user_data;
   4526 	struct wpa_ssid *ssid = net->ssid;
   4527 	DBusMessageIter	variant_iter;
   4528 
   4529 	dbus_message_iter_recurse(iter, &variant_iter);
   4530 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
   4531 }
   4532 
   4533 
   4534 #ifdef CONFIG_AP
   4535 
   4536 DBusMessage * wpas_dbus_handler_subscribe_preq(
   4537 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   4538 {
   4539 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
   4540 	char *name;
   4541 
   4542 	if (wpa_s->preq_notify_peer != NULL) {
   4543 		if (os_strcmp(dbus_message_get_sender(message),
   4544 			      wpa_s->preq_notify_peer) == 0)
   4545 			return NULL;
   4546 
   4547 		return dbus_message_new_error(message,
   4548 			WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE,
   4549 			"Another application is already subscribed");
   4550 	}
   4551 
   4552 	name = os_strdup(dbus_message_get_sender(message));
   4553 	if (!name)
   4554 		return wpas_dbus_error_no_memory(message);
   4555 
   4556 	wpa_s->preq_notify_peer = name;
   4557 
   4558 	/* Subscribe to clean up if application closes socket */
   4559 	wpas_dbus_subscribe_noc(priv);
   4560 
   4561 	/*
   4562 	 * Double-check it's still alive to make sure that we didn't
   4563 	 * miss the NameOwnerChanged signal, e.g. while strdup'ing.
   4564 	 */
   4565 	if (!dbus_bus_name_has_owner(priv->con, name, NULL)) {
   4566 		/*
   4567 		 * Application no longer exists, clean up.
   4568 		 * The return value is irrelevant now.
   4569 		 *
   4570 		 * Need to check if the NameOwnerChanged handling
   4571 		 * already cleaned up because we have processed
   4572 		 * DBus messages while checking if the name still
   4573 		 * has an owner.
   4574 		 */
   4575 		if (!wpa_s->preq_notify_peer)
   4576 			return NULL;
   4577 		os_free(wpa_s->preq_notify_peer);
   4578 		wpa_s->preq_notify_peer = NULL;
   4579 		wpas_dbus_unsubscribe_noc(priv);
   4580 	}
   4581 
   4582 	return NULL;
   4583 }
   4584 
   4585 
   4586 DBusMessage * wpas_dbus_handler_unsubscribe_preq(
   4587 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   4588 {
   4589 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
   4590 
   4591 	if (!wpa_s->preq_notify_peer)
   4592 		return dbus_message_new_error(message,
   4593 			WPAS_DBUS_ERROR_NO_SUBSCRIPTION,
   4594 			"Not subscribed");
   4595 
   4596 	if (os_strcmp(wpa_s->preq_notify_peer,
   4597 		      dbus_message_get_sender(message)))
   4598 		return dbus_message_new_error(message,
   4599 			WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM,
   4600 			"Can't unsubscribe others");
   4601 
   4602 	os_free(wpa_s->preq_notify_peer);
   4603 	wpa_s->preq_notify_peer = NULL;
   4604 	wpas_dbus_unsubscribe_noc(priv);
   4605 	return NULL;
   4606 }
   4607 
   4608 
   4609 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
   4610 			   const u8 *addr, const u8 *dst, const u8 *bssid,
   4611 			   const u8 *ie, size_t ie_len, u32 ssi_signal)
   4612 {
   4613 	DBusMessage *msg;
   4614 	DBusMessageIter iter, dict_iter;
   4615 	struct wpas_dbus_priv *priv = wpa_s->global->dbus;
   4616 
   4617 	/* Do nothing if the control interface is not turned on */
   4618 	if (priv == NULL || !wpa_s->dbus_new_path)
   4619 		return;
   4620 
   4621 	if (wpa_s->preq_notify_peer == NULL)
   4622 		return;
   4623 
   4624 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   4625 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
   4626 				      "ProbeRequest");
   4627 	if (msg == NULL)
   4628 		return;
   4629 
   4630 	dbus_message_set_destination(msg, wpa_s->preq_notify_peer);
   4631 
   4632 	dbus_message_iter_init_append(msg, &iter);
   4633 
   4634 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   4635 	    (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr",
   4636 						      (const char *) addr,
   4637 						      ETH_ALEN)) ||
   4638 	    (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst",
   4639 						     (const char *) dst,
   4640 						     ETH_ALEN)) ||
   4641 	    (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
   4642 						       (const char *) bssid,
   4643 						       ETH_ALEN)) ||
   4644 	    (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies",
   4645 							      (const char *) ie,
   4646 							      ie_len)) ||
   4647 	    (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal",
   4648 						       ssi_signal)) ||
   4649 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   4650 		goto fail;
   4651 
   4652 	dbus_connection_send(priv->con, msg, NULL);
   4653 	goto out;
   4654 fail:
   4655 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   4656 out:
   4657 	dbus_message_unref(msg);
   4658 }
   4659 
   4660 #endif /* CONFIG_AP */
   4661 
   4662 
   4663 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
   4664 						struct wpa_supplicant *wpa_s)
   4665 {
   4666 	u8 *ielems;
   4667 	int len;
   4668 	struct ieee802_11_elems elems;
   4669 	dbus_int32_t frame_id;
   4670 	DBusMessageIter	iter, array;
   4671 
   4672 	dbus_message_iter_init(message, &iter);
   4673 	dbus_message_iter_get_basic(&iter, &frame_id);
   4674 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
   4675 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4676 					      "Invalid ID");
   4677 	}
   4678 
   4679 	dbus_message_iter_next(&iter);
   4680 	dbus_message_iter_recurse(&iter, &array);
   4681 	dbus_message_iter_get_fixed_array(&array, &ielems, &len);
   4682 	if (!ielems || len == 0) {
   4683 		return dbus_message_new_error(
   4684 			message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
   4685 	}
   4686 
   4687 	if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
   4688 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4689 					      "Parse error");
   4690 	}
   4691 
   4692 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
   4693 	if (!wpa_s->vendor_elem[frame_id]) {
   4694 		wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
   4695 		wpas_vendor_elem_update(wpa_s);
   4696 		return NULL;
   4697 	}
   4698 
   4699 	if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
   4700 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4701 					      "Resize error");
   4702 	}
   4703 
   4704 	wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
   4705 	wpas_vendor_elem_update(wpa_s);
   4706 	return NULL;
   4707 }
   4708 
   4709 
   4710 DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
   4711 						struct wpa_supplicant *wpa_s)
   4712 {
   4713 	DBusMessage *reply;
   4714 	DBusMessageIter	iter, array_iter;
   4715 	dbus_int32_t frame_id;
   4716 	const u8 *elem;
   4717 	size_t elem_len;
   4718 
   4719 	dbus_message_iter_init(message, &iter);
   4720 	dbus_message_iter_get_basic(&iter, &frame_id);
   4721 
   4722 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
   4723 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4724 					      "Invalid ID");
   4725 	}
   4726 
   4727 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
   4728 	if (!wpa_s->vendor_elem[frame_id]) {
   4729 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4730 					      "ID value does not exist");
   4731 	}
   4732 
   4733 	reply = dbus_message_new_method_return(message);
   4734 	if (!reply)
   4735 		return wpas_dbus_error_no_memory(message);
   4736 
   4737 	dbus_message_iter_init_append(reply, &iter);
   4738 
   4739 	elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
   4740 	elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
   4741 
   4742 	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
   4743 					      DBUS_TYPE_BYTE_AS_STRING,
   4744 					      &array_iter) ||
   4745 	    !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
   4746 						  &elem, elem_len) ||
   4747 	    !dbus_message_iter_close_container(&iter, &array_iter)) {
   4748 		dbus_message_unref(reply);
   4749 		reply = wpas_dbus_error_no_memory(message);
   4750 	}
   4751 
   4752 	return reply;
   4753 }
   4754 
   4755 
   4756 DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
   4757 						   struct wpa_supplicant *wpa_s)
   4758 {
   4759 	u8 *ielems;
   4760 	int len;
   4761 	struct ieee802_11_elems elems;
   4762 	DBusMessageIter	iter, array;
   4763 	dbus_int32_t frame_id;
   4764 
   4765 	dbus_message_iter_init(message, &iter);
   4766 	dbus_message_iter_get_basic(&iter, &frame_id);
   4767 	if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
   4768 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4769 					      "Invalid ID");
   4770 	}
   4771 
   4772 	dbus_message_iter_next(&iter);
   4773 	dbus_message_iter_recurse(&iter, &array);
   4774 	dbus_message_iter_get_fixed_array(&array, &ielems, &len);
   4775 	if (!ielems || len == 0) {
   4776 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4777 					      "Invalid value");
   4778 	}
   4779 
   4780 	wpa_s = wpas_vendor_elem(wpa_s, frame_id);
   4781 
   4782 	if (len == 1 && *ielems == '*') {
   4783 		wpabuf_free(wpa_s->vendor_elem[frame_id]);
   4784 		wpa_s->vendor_elem[frame_id] = NULL;
   4785 		wpas_vendor_elem_update(wpa_s);
   4786 		return NULL;
   4787 	}
   4788 
   4789 	if (!wpa_s->vendor_elem[frame_id]) {
   4790 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4791 					      "ID value does not exist");
   4792 	}
   4793 
   4794 	if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
   4795 		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4796 					      "Parse error");
   4797 	}
   4798 
   4799 	if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
   4800 		return NULL;
   4801 
   4802 	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
   4803 				      "Not found");
   4804 }
   4805 
   4806 
   4807 #ifdef CONFIG_MESH
   4808 
   4809 /**
   4810  * wpas_dbus_getter_mesh_peers - Get connected mesh peers
   4811  * @iter: Pointer to incoming dbus message iter
   4812  * @error: Location to store error on failure
   4813  * @user_data: Function specific data
   4814  * Returns: TRUE on success, FALSE on failure
   4815  *
   4816  * Getter for "MeshPeers" property.
   4817  */
   4818 dbus_bool_t wpas_dbus_getter_mesh_peers(
   4819 	const struct wpa_dbus_property_desc *property_desc,
   4820 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4821 {
   4822 	struct wpa_supplicant *wpa_s = user_data;
   4823 	struct hostapd_data *hapd;
   4824 	struct sta_info *sta;
   4825 	DBusMessageIter variant_iter, array_iter;
   4826 	int i;
   4827 	DBusMessageIter inner_array_iter;
   4828 
   4829 	if (!wpa_s->ifmsh)
   4830 		return FALSE;
   4831 	hapd = wpa_s->ifmsh->bss[0];
   4832 
   4833 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   4834 					      DBUS_TYPE_ARRAY_AS_STRING
   4835 					      DBUS_TYPE_ARRAY_AS_STRING
   4836 					      DBUS_TYPE_BYTE_AS_STRING,
   4837 					      &variant_iter) ||
   4838 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
   4839 					      DBUS_TYPE_ARRAY_AS_STRING
   4840 					      DBUS_TYPE_BYTE_AS_STRING,
   4841 					      &array_iter))
   4842 		return FALSE;
   4843 
   4844 	for (sta = hapd->sta_list; sta; sta = sta->next) {
   4845 		if (!dbus_message_iter_open_container(
   4846 			    &array_iter, DBUS_TYPE_ARRAY,
   4847 			    DBUS_TYPE_BYTE_AS_STRING,
   4848 			    &inner_array_iter))
   4849 			return FALSE;
   4850 
   4851 		for (i = 0; i < ETH_ALEN; i++) {
   4852 			if (!dbus_message_iter_append_basic(&inner_array_iter,
   4853 							    DBUS_TYPE_BYTE,
   4854 							    &(sta->addr[i])))
   4855 				return FALSE;
   4856 		}
   4857 
   4858 		if (!dbus_message_iter_close_container(
   4859 			    &array_iter, &inner_array_iter))
   4860 			return FALSE;
   4861 	}
   4862 
   4863 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
   4864 	    !dbus_message_iter_close_container(iter, &variant_iter))
   4865 		return FALSE;
   4866 
   4867 	return TRUE;
   4868 }
   4869 
   4870 
   4871 /**
   4872  * wpas_dbus_getter_mesh_group - Get mesh group
   4873  * @iter: Pointer to incoming dbus message iter
   4874  * @error: Location to store error on failure
   4875  * @user_data: Function specific data
   4876  * Returns: TRUE on success, FALSE on failure
   4877  *
   4878  * Getter for "MeshGroup" property.
   4879  */
   4880 dbus_bool_t wpas_dbus_getter_mesh_group(
   4881 	const struct wpa_dbus_property_desc *property_desc,
   4882 	DBusMessageIter *iter, DBusError *error, void *user_data)
   4883 {
   4884 	struct wpa_supplicant *wpa_s = user_data;
   4885 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   4886 
   4887 	if (!wpa_s->ifmsh || !ssid)
   4888 		return FALSE;
   4889 
   4890 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   4891 						    (char *) ssid->ssid,
   4892 						    ssid->ssid_len, error)) {
   4893 		dbus_set_error(error, DBUS_ERROR_FAILED,
   4894 			       "%s: error constructing reply", __func__);
   4895 		return FALSE;
   4896 	}
   4897 
   4898 	return TRUE;
   4899 }
   4900 
   4901 #endif /* CONFIG_MESH */
   4902