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