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