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