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