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