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