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