Home | History | Annotate | Download | only in dbus
      1 /*
      2  * WPA Supplicant / dbus-based control interface (P2P)
      3  * Copyright (c) 2011-2012, Intel Corporation
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "utils/includes.h"
     12 #include "common.h"
     13 #include "../config.h"
     14 #include "../wpa_supplicant_i.h"
     15 #include "../wps_supplicant.h"
     16 #include "../notify.h"
     17 #include "dbus_new_helpers.h"
     18 #include "dbus_new.h"
     19 #include "dbus_new_handlers.h"
     20 #include "dbus_new_handlers_p2p.h"
     21 #include "dbus_dict_helpers.h"
     22 #include "p2p/p2p.h"
     23 #include "common/ieee802_11_defs.h"
     24 #include "ap/hostapd.h"
     25 #include "ap/ap_config.h"
     26 #include "ap/wps_hostapd.h"
     27 
     28 #include "../p2p_supplicant.h"
     29 #include "../wifi_display.h"
     30 
     31 
     32 static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
     33 {
     34 	if (entry.type != DBUS_TYPE_ARRAY ||
     35 	    entry.array_type != DBUS_TYPE_BYTE ||
     36 	    entry.array_len != 4)
     37 		return 0;
     38 
     39 	return 1;
     40 }
     41 
     42 
     43 /**
     44  * Parses out the mac address from the peer object path.
     45  * @peer_path - object path of the form
     46  *	/fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
     47  * @addr - out param must be of ETH_ALEN size
     48  * Returns 0 if valid (including MAC), -1 otherwise
     49  */
     50 static int parse_peer_object_path(const char *peer_path, u8 addr[ETH_ALEN])
     51 {
     52 	const char *p;
     53 
     54 	if (!peer_path)
     55 		return -1;
     56 	p = os_strrchr(peer_path, '/');
     57 	if (!p)
     58 		return -1;
     59 	p++;
     60 	return hwaddr_compact_aton(p, addr);
     61 }
     62 
     63 
     64 /**
     65  * wpas_dbus_error_persistent_group_unknown - Return a new PersistentGroupUnknown
     66  * error message
     67  * @message: Pointer to incoming dbus message this error refers to
     68  * Returns: a dbus error message
     69  *
     70  * Convenience function to create and return an invalid persistent group error.
     71  */
     72 static DBusMessage *
     73 wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
     74 {
     75 	return dbus_message_new_error(
     76 		message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
     77 		"There is no such persistent group in this P2P device.");
     78 }
     79 
     80 
     81 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
     82 					 struct wpa_supplicant *wpa_s)
     83 {
     84 	struct wpa_dbus_dict_entry entry;
     85 	DBusMessage *reply = NULL;
     86 	DBusMessageIter iter;
     87 	DBusMessageIter iter_dict;
     88 	unsigned int timeout = 0;
     89 	enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
     90 	int num_req_dev_types = 0;
     91 	unsigned int i;
     92 	u8 *req_dev_types = NULL;
     93 	unsigned int freq = 0;
     94 
     95 	dbus_message_iter_init(message, &iter);
     96 	entry.key = NULL;
     97 
     98 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
     99 		goto error;
    100 
    101 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    102 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    103 			goto error;
    104 
    105 		if (os_strcmp(entry.key, "Timeout") == 0 &&
    106 		    entry.type == DBUS_TYPE_INT32) {
    107 			timeout = entry.uint32_value;
    108 		} else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
    109 			if (entry.type != DBUS_TYPE_ARRAY ||
    110 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY)
    111 				goto error_clear;
    112 
    113 			os_free(req_dev_types);
    114 			req_dev_types =
    115 				os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
    116 			if (!req_dev_types)
    117 				goto error_clear;
    118 
    119 			for (i = 0; i < entry.array_len; i++) {
    120 				if (wpabuf_len(entry.binarray_value[i]) !=
    121 				    WPS_DEV_TYPE_LEN)
    122 					goto error_clear;
    123 				os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
    124 					  wpabuf_head(entry.binarray_value[i]),
    125 					  WPS_DEV_TYPE_LEN);
    126 			}
    127 			num_req_dev_types = entry.array_len;
    128 		} else if (os_strcmp(entry.key, "DiscoveryType") == 0 &&
    129 			   entry.type == DBUS_TYPE_STRING) {
    130 			if (os_strcmp(entry.str_value, "start_with_full") == 0)
    131 				type = P2P_FIND_START_WITH_FULL;
    132 			else if (os_strcmp(entry.str_value, "social") == 0)
    133 				type = P2P_FIND_ONLY_SOCIAL;
    134 			else if (os_strcmp(entry.str_value, "progressive") == 0)
    135 				type = P2P_FIND_PROGRESSIVE;
    136 			else
    137 				goto error_clear;
    138 		} else if (os_strcmp(entry.key, "freq") == 0 &&
    139 			   (entry.type == DBUS_TYPE_INT32 ||
    140 			    entry.type == DBUS_TYPE_UINT32)) {
    141 			freq = entry.uint32_value;
    142 		} else
    143 			goto error_clear;
    144 		wpa_dbus_dict_entry_clear(&entry);
    145 	}
    146 
    147 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    148 
    149 	wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
    150 		      NULL, 0, 0, NULL, freq);
    151 	os_free(req_dev_types);
    152 	return reply;
    153 
    154 error_clear:
    155 	wpa_dbus_dict_entry_clear(&entry);
    156 error:
    157 	os_free(req_dev_types);
    158 	reply = wpas_dbus_error_invalid_args(message, entry.key);
    159 	return reply;
    160 }
    161 
    162 
    163 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
    164 					      struct wpa_supplicant *wpa_s)
    165 {
    166 	wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
    167 	return NULL;
    168 }
    169 
    170 
    171 DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
    172 					       struct wpa_supplicant *wpa_s)
    173 {
    174 	DBusMessageIter iter;
    175 	char *peer_object_path = NULL;
    176 	u8 peer_addr[ETH_ALEN];
    177 
    178 	dbus_message_iter_init(message, &iter);
    179 	dbus_message_iter_get_basic(&iter, &peer_object_path);
    180 
    181 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
    182 		return wpas_dbus_error_invalid_args(message, NULL);
    183 
    184 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    185 
    186 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
    187 		return wpas_dbus_error_unknown_error(message,
    188 				"Failed to call wpas_p2p_reject method.");
    189 
    190 	return NULL;
    191 }
    192 
    193 
    194 DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
    195 					   struct wpa_supplicant *wpa_s)
    196 {
    197 	dbus_int32_t timeout = 0;
    198 
    199 	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
    200 				   DBUS_TYPE_INVALID))
    201 		return wpas_dbus_error_no_memory(message);
    202 
    203 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    204 
    205 	if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
    206 		return dbus_message_new_error(message,
    207 					      WPAS_DBUS_ERROR_UNKNOWN_ERROR,
    208 					      "Could not start P2P listen");
    209 	}
    210 
    211 	return NULL;
    212 }
    213 
    214 
    215 DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
    216 	DBusMessage *message, struct wpa_supplicant *wpa_s)
    217 {
    218 	unsigned int period = 0, interval = 0;
    219 	struct wpa_dbus_dict_entry entry;
    220 	DBusMessageIter iter;
    221 	DBusMessageIter iter_dict;
    222 
    223 	dbus_message_iter_init(message, &iter);
    224 	entry.key = NULL;
    225 
    226 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    227 		goto error;
    228 
    229 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    230 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    231 			goto error;
    232 
    233 		if (os_strcmp(entry.key, "period") == 0 &&
    234 		    entry.type == DBUS_TYPE_INT32)
    235 			period = entry.uint32_value;
    236 		else if (os_strcmp(entry.key, "interval") == 0 &&
    237 			 entry.type == DBUS_TYPE_INT32)
    238 			interval = entry.uint32_value;
    239 		else
    240 			goto error_clear;
    241 		wpa_dbus_dict_entry_clear(&entry);
    242 	}
    243 
    244 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    245 
    246 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
    247 		return wpas_dbus_error_unknown_error(
    248 			message, "failed to initiate a p2p_ext_listen.");
    249 
    250 	return NULL;
    251 
    252 error_clear:
    253 	wpa_dbus_dict_entry_clear(&entry);
    254 error:
    255 	return wpas_dbus_error_invalid_args(message, entry.key);
    256 }
    257 
    258 
    259 DBusMessage * wpas_dbus_handler_p2p_presence_request(
    260 	DBusMessage *message, struct wpa_supplicant *wpa_s)
    261 {
    262 	unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
    263 	struct wpa_dbus_dict_entry entry;
    264 	DBusMessageIter iter;
    265 	DBusMessageIter iter_dict;
    266 
    267 	dbus_message_iter_init(message, &iter);
    268 	entry.key = NULL;
    269 
    270 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    271 		goto error;
    272 
    273 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    274 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    275 			goto error;
    276 
    277 		if (os_strcmp(entry.key, "duration1") == 0 &&
    278 		    entry.type == DBUS_TYPE_INT32)
    279 			dur1 = entry.uint32_value;
    280 		else if (os_strcmp(entry.key, "interval1") == 0 &&
    281 			 entry.type == DBUS_TYPE_INT32)
    282 			int1 = entry.uint32_value;
    283 		else if (os_strcmp(entry.key, "duration2") == 0 &&
    284 			 entry.type == DBUS_TYPE_INT32)
    285 			dur2 = entry.uint32_value;
    286 		else if (os_strcmp(entry.key, "interval2") == 0 &&
    287 			 entry.type == DBUS_TYPE_INT32)
    288 			int2 = entry.uint32_value;
    289 		else
    290 			goto error_clear;
    291 
    292 		wpa_dbus_dict_entry_clear(&entry);
    293 	}
    294 
    295 	if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
    296 		return wpas_dbus_error_unknown_error(message,
    297 				"Failed to invoke presence request.");
    298 
    299 	return NULL;
    300 
    301 error_clear:
    302 	wpa_dbus_dict_entry_clear(&entry);
    303 error:
    304 	return wpas_dbus_error_invalid_args(message, entry.key);
    305 }
    306 
    307 
    308 DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
    309 					      struct wpa_supplicant *wpa_s)
    310 {
    311 	DBusMessageIter iter_dict;
    312 	DBusMessage *reply = NULL;
    313 	DBusMessageIter iter;
    314 	struct wpa_dbus_dict_entry entry;
    315 	char *pg_object_path = NULL;
    316 	int persistent_group = 0;
    317 	int freq = 0;
    318 	char *iface = NULL;
    319 	unsigned int group_id = 0;
    320 	struct wpa_ssid *ssid;
    321 
    322 	dbus_message_iter_init(message, &iter);
    323 
    324 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    325 		goto inv_args;
    326 
    327 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    328 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    329 			goto inv_args;
    330 
    331 		if (os_strcmp(entry.key, "persistent") == 0 &&
    332 		    entry.type == DBUS_TYPE_BOOLEAN) {
    333 			persistent_group = entry.bool_value;
    334 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
    335 			   entry.type == DBUS_TYPE_INT32) {
    336 			freq = entry.int32_value;
    337 			if (freq <= 0)
    338 				goto inv_args_clear;
    339 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
    340 			   0 &&
    341 			   entry.type == DBUS_TYPE_OBJECT_PATH)
    342 			pg_object_path = os_strdup(entry.str_value);
    343 		else
    344 			goto inv_args_clear;
    345 
    346 		wpa_dbus_dict_entry_clear(&entry);
    347 	}
    348 
    349 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    350 
    351 	if (pg_object_path != NULL) {
    352 		char *net_id_str;
    353 
    354 		/*
    355 		 * A persistent group Object Path is defined meaning we want
    356 		 * to re-invoke a persistent group.
    357 		 */
    358 
    359 		iface = wpas_dbus_new_decompose_object_path(
    360 			pg_object_path, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
    361 			&net_id_str);
    362 		if (iface == NULL || net_id_str == NULL ||
    363 		    !wpa_s->parent->dbus_new_path ||
    364 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
    365 			reply =
    366 			    wpas_dbus_error_invalid_args(message,
    367 							 pg_object_path);
    368 			goto out;
    369 		}
    370 
    371 		group_id = strtoul(net_id_str, NULL, 10);
    372 		if (errno == EINVAL) {
    373 			reply = wpas_dbus_error_invalid_args(
    374 						message, pg_object_path);
    375 			goto out;
    376 		}
    377 
    378 		/* Get the SSID structure from the persistent group id */
    379 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
    380 		if (ssid == NULL || ssid->disabled != 2)
    381 			goto inv_args;
    382 
    383 		if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
    384 						  0, 0, NULL, 0, 0)) {
    385 			reply = wpas_dbus_error_unknown_error(
    386 				message,
    387 				"Failed to reinvoke a persistent group");
    388 			goto out;
    389 		}
    390 	} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
    391 				      0))
    392 		goto inv_args;
    393 
    394 out:
    395 	os_free(pg_object_path);
    396 	os_free(iface);
    397 	return reply;
    398 inv_args_clear:
    399 	wpa_dbus_dict_entry_clear(&entry);
    400 inv_args:
    401 	reply = wpas_dbus_error_invalid_args(message, NULL);
    402 	goto out;
    403 }
    404 
    405 
    406 DBusMessage * wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
    407 					       struct wpa_supplicant *wpa_s)
    408 {
    409 	if (wpas_p2p_disconnect(wpa_s))
    410 		return wpas_dbus_error_unknown_error(message,
    411 						"failed to disconnect");
    412 
    413 	return NULL;
    414 }
    415 
    416 
    417 static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
    418 					      DBusMessage *message,
    419 					      DBusMessage **out_reply,
    420 					      DBusError *error)
    421 {
    422 	/* Return an error message or an error if P2P isn't available */
    423 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
    424 		if (out_reply) {
    425 			*out_reply = dbus_message_new_error(
    426 				message, DBUS_ERROR_FAILED,
    427 				"P2P is not available for this interface");
    428 		}
    429 		dbus_set_error_const(error, DBUS_ERROR_FAILED,
    430 				     "P2P is not available for this interface");
    431 		return FALSE;
    432 	}
    433 	return TRUE;
    434 }
    435 
    436 
    437 DBusMessage * wpas_dbus_handler_p2p_remove_client(DBusMessage *message,
    438 						  struct wpa_supplicant *wpa_s)
    439 {
    440 	DBusMessageIter iter_dict;
    441 	DBusMessage *reply = NULL;
    442 	DBusMessageIter iter;
    443 	struct wpa_dbus_dict_entry entry;
    444 	char *peer_object_path = NULL;
    445 	char *interface_addr = NULL;
    446 	u8 peer_addr[ETH_ALEN];
    447 
    448 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
    449 		return reply;
    450 
    451 	dbus_message_iter_init(message, &iter);
    452 
    453 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    454 		goto err;
    455 
    456 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    457 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    458 			goto err;
    459 
    460 		if (os_strcmp(entry.key, "peer") == 0 &&
    461 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
    462 			os_free(peer_object_path);
    463 			peer_object_path = os_strdup(entry.str_value);
    464 			wpa_dbus_dict_entry_clear(&entry);
    465 		} else if (os_strcmp(entry.key, "iface") == 0 &&
    466 			   entry.type == DBUS_TYPE_STRING) {
    467 			os_free(interface_addr);
    468 			interface_addr = os_strdup(entry.str_value);
    469 			wpa_dbus_dict_entry_clear(&entry);
    470 		} else {
    471 			wpa_dbus_dict_entry_clear(&entry);
    472 			goto err;
    473 		}
    474 	}
    475 
    476 	if ((!peer_object_path && !interface_addr) ||
    477 	    (peer_object_path &&
    478 	     (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
    479 	      !p2p_peer_known(wpa_s->global->p2p, peer_addr))) ||
    480 	    (interface_addr && hwaddr_aton(interface_addr, peer_addr) < 0))
    481 		goto err;
    482 
    483 	wpas_p2p_remove_client(wpa_s, peer_addr, interface_addr != NULL);
    484 	reply = NULL;
    485 out:
    486 	os_free(peer_object_path);
    487 	os_free(interface_addr);
    488 	return reply;
    489 err:
    490 	reply = wpas_dbus_error_invalid_args(message, "Invalid address format");
    491 	goto out;
    492 }
    493 
    494 
    495 DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
    496 					  struct wpa_supplicant *wpa_s)
    497 {
    498 	DBusMessage *reply = NULL;
    499 
    500 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
    501 		return reply;
    502 
    503 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    504 
    505 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
    506 	wpa_s->force_long_sd = 0;
    507 	p2p_flush(wpa_s->global->p2p);
    508 
    509 	return NULL;
    510 }
    511 
    512 
    513 DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
    514 					    struct wpa_supplicant *wpa_s)
    515 {
    516 	DBusMessageIter iter_dict;
    517 	DBusMessage *reply = NULL;
    518 	DBusMessageIter iter;
    519 	struct wpa_dbus_dict_entry entry;
    520 	char *peer_object_path = NULL;
    521 	int persistent_group = 0;
    522 	int join = 0;
    523 	int authorize_only = 0;
    524 	int go_intent = -1;
    525 	int freq = 0;
    526 	u8 addr[ETH_ALEN];
    527 	char *pin = NULL;
    528 	enum p2p_wps_method wps_method = WPS_NOT_READY;
    529 	int new_pin;
    530 	char *err_msg = NULL;
    531 	char *iface = NULL;
    532 
    533 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
    534 		return reply;
    535 
    536 	dbus_message_iter_init(message, &iter);
    537 
    538 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    539 		goto inv_args;
    540 
    541 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    542 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    543 			goto inv_args;
    544 
    545 		if (os_strcmp(entry.key, "peer") == 0 &&
    546 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
    547 			peer_object_path = os_strdup(entry.str_value);
    548 		} else if (os_strcmp(entry.key, "persistent") == 0 &&
    549 			   entry.type == DBUS_TYPE_BOOLEAN) {
    550 			persistent_group = entry.bool_value;
    551 		} else if (os_strcmp(entry.key, "join") == 0 &&
    552 			   entry.type == DBUS_TYPE_BOOLEAN) {
    553 			join = entry.bool_value;
    554 		} else if (os_strcmp(entry.key, "authorize_only") == 0 &&
    555 			   entry.type == DBUS_TYPE_BOOLEAN) {
    556 			authorize_only = entry.bool_value;
    557 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
    558 			   entry.type == DBUS_TYPE_INT32) {
    559 			freq = entry.int32_value;
    560 			if (freq <= 0)
    561 				goto inv_args_clear;
    562 		} else if (os_strcmp(entry.key, "go_intent") == 0 &&
    563 			   entry.type == DBUS_TYPE_INT32) {
    564 			go_intent = entry.int32_value;
    565 			if ((go_intent < 0) || (go_intent > 15))
    566 				goto inv_args_clear;
    567 		} else if (os_strcmp(entry.key, "wps_method") == 0 &&
    568 			   entry.type == DBUS_TYPE_STRING) {
    569 			if (os_strcmp(entry.str_value, "pbc") == 0)
    570 				wps_method = WPS_PBC;
    571 			else if (os_strcmp(entry.str_value, "pin") == 0)
    572 				wps_method = WPS_PIN_DISPLAY;
    573 			else if (os_strcmp(entry.str_value, "display") == 0)
    574 				wps_method = WPS_PIN_DISPLAY;
    575 			else if (os_strcmp(entry.str_value, "keypad") == 0)
    576 				wps_method = WPS_PIN_KEYPAD;
    577 			else
    578 				goto inv_args_clear;
    579 		} else if (os_strcmp(entry.key, "pin") == 0 &&
    580 			   entry.type == DBUS_TYPE_STRING) {
    581 			pin = os_strdup(entry.str_value);
    582 		} else
    583 			goto inv_args_clear;
    584 
    585 		wpa_dbus_dict_entry_clear(&entry);
    586 	}
    587 
    588 	if (wps_method == WPS_NOT_READY ||
    589 	    parse_peer_object_path(peer_object_path, addr) < 0 ||
    590 	    !p2p_peer_known(wpa_s->global->p2p, addr))
    591 		goto inv_args;
    592 
    593 	/*
    594 	 * Validate the wps_method specified and the pin value.
    595 	 */
    596 	if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
    597 		goto inv_args;
    598 
    599 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    600 
    601 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
    602 				   persistent_group, 0, join, authorize_only,
    603 				   go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
    604 
    605 	if (new_pin >= 0) {
    606 		char npin[9];
    607 		char *generated_pin;
    608 
    609 		os_snprintf(npin, sizeof(npin), "%08d", new_pin);
    610 		generated_pin = npin;
    611 		reply = dbus_message_new_method_return(message);
    612 		dbus_message_append_args(reply, DBUS_TYPE_STRING,
    613 					 &generated_pin, DBUS_TYPE_INVALID);
    614 	} else {
    615 		switch (new_pin) {
    616 		case -2:
    617 			err_msg =
    618 				"connect failed due to channel unavailability.";
    619 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
    620 			break;
    621 
    622 		case -3:
    623 			err_msg = "connect failed due to unsupported channel.";
    624 			iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
    625 			break;
    626 
    627 		default:
    628 			err_msg = "connect failed due to unspecified error.";
    629 			iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
    630 			break;
    631 		}
    632 
    633 		/*
    634 		 * TODO:
    635 		 * Do we need specialized errors corresponding to above
    636 		 * error conditions as against just returning a different
    637 		 * error message?
    638 		 */
    639 		reply = dbus_message_new_error(message, iface, err_msg);
    640 	}
    641 
    642 out:
    643 	os_free(peer_object_path);
    644 	os_free(pin);
    645 	return reply;
    646 inv_args_clear:
    647 	wpa_dbus_dict_entry_clear(&entry);
    648 inv_args:
    649 	reply = wpas_dbus_error_invalid_args(message, NULL);
    650 	goto out;
    651 }
    652 
    653 
    654 /**
    655  * wpas_dbus_handler_p2p_cancel - Cancel P2P group formation
    656  * @message: Pointer to incoming dbus message
    657  * @wpa_s: %wpa_supplicant data structure
    658  * Returns: NULL on success or DBus error on failure
    659  *
    660  * Handler for "Cancel" method call. Returns NULL if P2P cancel succeeds or DBus
    661  * error on P2P cancel failure
    662  */
    663 DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
    664 					   struct wpa_supplicant *wpa_s)
    665 {
    666 	if (wpas_p2p_cancel(wpa_s))
    667 		return wpas_dbus_error_unknown_error(message,
    668 						     "P2P cancel failed");
    669 
    670 	return NULL;
    671 }
    672 
    673 
    674 DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
    675 					   struct wpa_supplicant *wpa_s)
    676 {
    677 	DBusMessageIter iter_dict;
    678 	DBusMessage *reply = NULL;
    679 	DBusMessageIter iter;
    680 	struct wpa_dbus_dict_entry entry;
    681 	char *peer_object_path = NULL;
    682 	char *pg_object_path = NULL;
    683 	char *iface = NULL;
    684 	u8 peer_addr[ETH_ALEN];
    685 	unsigned int group_id = 0;
    686 	int persistent = 0;
    687 	struct wpa_ssid *ssid;
    688 
    689 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
    690 		return reply;
    691 
    692 	dbus_message_iter_init(message, &iter);
    693 
    694 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
    695 		goto err;
    696 
    697 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    698 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
    699 			goto err;
    700 
    701 		if (os_strcmp(entry.key, "peer") == 0 &&
    702 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
    703 			peer_object_path = os_strdup(entry.str_value);
    704 			wpa_dbus_dict_entry_clear(&entry);
    705 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
    706 			   0 &&
    707 			   entry.type == DBUS_TYPE_OBJECT_PATH) {
    708 			pg_object_path = os_strdup(entry.str_value);
    709 			persistent = 1;
    710 			wpa_dbus_dict_entry_clear(&entry);
    711 		} else {
    712 			wpa_dbus_dict_entry_clear(&entry);
    713 			goto err;
    714 		}
    715 	}
    716 
    717 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
    718 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
    719 		goto err;
    720 
    721 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    722 
    723 	if (persistent) {
    724 		char *net_id_str;
    725 		/*
    726 		 * A group ID is defined meaning we want to re-invoke a
    727 		 * persistent group
    728 		 */
    729 
    730 		iface = wpas_dbus_new_decompose_object_path(
    731 			pg_object_path,
    732 			WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
    733 			&net_id_str);
    734 		if (iface == NULL || net_id_str == NULL ||
    735 		    !wpa_s->parent->dbus_new_path ||
    736 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
    737 			reply = wpas_dbus_error_invalid_args(message,
    738 							     pg_object_path);
    739 			goto out;
    740 		}
    741 
    742 		group_id = strtoul(net_id_str, NULL, 10);
    743 		if (errno == EINVAL) {
    744 			reply = wpas_dbus_error_invalid_args(
    745 				message, pg_object_path);
    746 			goto out;
    747 		}
    748 
    749 		/* Get the SSID structure from the persistent group id */
    750 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
    751 		if (ssid == NULL || ssid->disabled != 2)
    752 			goto err;
    753 
    754 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
    755 				    0) < 0) {
    756 			reply = wpas_dbus_error_unknown_error(
    757 				message,
    758 				"Failed to reinvoke a persistent group");
    759 			goto out;
    760 		}
    761 	} else {
    762 		/*
    763 		 * No group ID means propose to a peer to join my active group
    764 		 */
    765 		if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
    766 					  peer_addr, NULL)) {
    767 			reply = wpas_dbus_error_unknown_error(
    768 				message, "Failed to join to an active group");
    769 			goto out;
    770 		}
    771 	}
    772 
    773 out:
    774 	os_free(iface);
    775 	os_free(pg_object_path);
    776 	os_free(peer_object_path);
    777 	return reply;
    778 
    779 err:
    780 	reply = wpas_dbus_error_invalid_args(message, NULL);
    781 	goto out;
    782 }
    783 
    784 
    785 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
    786 						  struct wpa_supplicant *wpa_s)
    787 {
    788 	DBusMessageIter iter;
    789 	char *peer_object_path = NULL;
    790 	char *config_method = NULL;
    791 	u8 peer_addr[ETH_ALEN];
    792 
    793 	dbus_message_iter_init(message, &iter);
    794 	dbus_message_iter_get_basic(&iter, &peer_object_path);
    795 
    796 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
    797 		return wpas_dbus_error_invalid_args(message, NULL);
    798 
    799 	dbus_message_iter_next(&iter);
    800 	dbus_message_iter_get_basic(&iter, &config_method);
    801 
    802 	/*
    803 	 * Validation checks on config_method are being duplicated here
    804 	 * to be able to return invalid args reply since the error code
    805 	 * from p2p module are not granular enough (yet).
    806 	 */
    807 	if (os_strcmp(config_method, "display") &&
    808 	    os_strcmp(config_method, "keypad") &&
    809 	    os_strcmp(config_method, "pbc") &&
    810 	    os_strcmp(config_method, "pushbutton"))
    811 		return wpas_dbus_error_invalid_args(message, NULL);
    812 
    813 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    814 
    815 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
    816 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
    817 		return wpas_dbus_error_unknown_error(message,
    818 				"Failed to send provision discovery request");
    819 
    820 	return NULL;
    821 }
    822 
    823 
    824 /*
    825  * P2P Device property accessor methods.
    826  */
    827 
    828 dbus_bool_t wpas_dbus_getter_p2p_device_config(
    829 	const struct wpa_dbus_property_desc *property_desc,
    830 	DBusMessageIter *iter, DBusError *error, void *user_data)
    831 {
    832 	struct wpa_supplicant *wpa_s = user_data;
    833 	DBusMessageIter variant_iter, dict_iter;
    834 	DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
    835 		iter_secdev_dict_array;
    836 	const char *dev_name;
    837 	int num_vendor_extensions = 0;
    838 	int i;
    839 	const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
    840 
    841 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
    842 		return FALSE;
    843 
    844 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    845 
    846 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
    847 					      "a{sv}", &variant_iter) ||
    848 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
    849 		goto err_no_mem;
    850 
    851 	/* DeviceName */
    852 	dev_name = wpa_s->conf->device_name;
    853 	if (dev_name &&
    854 	    !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
    855 		goto err_no_mem;
    856 
    857 	/* Primary device type */
    858 	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
    859 					     (char *) wpa_s->conf->device_type,
    860 					     WPS_DEV_TYPE_LEN))
    861 		goto err_no_mem;
    862 
    863 	/* Secondary device types */
    864 	if (wpa_s->conf->num_sec_device_types) {
    865 		if (!wpa_dbus_dict_begin_array(&dict_iter,
    866 					       "SecondaryDeviceTypes",
    867 					       DBUS_TYPE_ARRAY_AS_STRING
    868 					       DBUS_TYPE_BYTE_AS_STRING,
    869 					       &iter_secdev_dict_entry,
    870 					       &iter_secdev_dict_val,
    871 					       &iter_secdev_dict_array))
    872 			goto err_no_mem;
    873 
    874 		for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
    875 			wpa_dbus_dict_bin_array_add_element(
    876 				&iter_secdev_dict_array,
    877 				wpa_s->conf->sec_device_type[i],
    878 				WPS_DEV_TYPE_LEN);
    879 
    880 		if (!wpa_dbus_dict_end_array(&dict_iter,
    881 					     &iter_secdev_dict_entry,
    882 					     &iter_secdev_dict_val,
    883 					     &iter_secdev_dict_array))
    884 			goto err_no_mem;
    885 	}
    886 
    887 	/* GO IP address */
    888 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
    889 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
    890 					     (char *) wpa_s->conf->ip_addr_go,
    891 					     4))
    892 		goto err_no_mem;
    893 
    894 	/* IP address mask */
    895 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
    896 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
    897 					     (char *) wpa_s->conf->ip_addr_mask,
    898 					     4))
    899 		goto err_no_mem;
    900 
    901 	/* IP address start */
    902 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
    903 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
    904 					     (char *)
    905 					     wpa_s->conf->ip_addr_start,
    906 					     4))
    907 		goto err_no_mem;
    908 
    909 	/* IP address end */
    910 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
    911 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
    912 					     (char *) wpa_s->conf->ip_addr_end,
    913 					     4))
    914 		goto err_no_mem;
    915 
    916 	/* Vendor Extensions */
    917 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
    918 		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
    919 			continue;
    920 		vendor_ext[num_vendor_extensions++] =
    921 			wpa_s->conf->wps_vendor_ext[i];
    922 	}
    923 
    924 	if ((num_vendor_extensions &&
    925 	     !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
    926 						"VendorExtension",
    927 						vendor_ext,
    928 						num_vendor_extensions)) ||
    929 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
    930 					 wpa_s->conf->p2p_go_intent) ||
    931 	    !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
    932 				       wpa_s->conf->persistent_reconnect) ||
    933 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
    934 					 wpa_s->conf->p2p_listen_reg_class) ||
    935 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
    936 					 wpa_s->conf->p2p_listen_channel) ||
    937 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
    938 					 wpa_s->conf->p2p_oper_reg_class) ||
    939 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
    940 					 wpa_s->conf->p2p_oper_channel) ||
    941 	    (wpa_s->conf->p2p_ssid_postfix &&
    942 	     !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
    943 					  wpa_s->conf->p2p_ssid_postfix)) ||
    944 	    !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
    945 				       wpa_s->conf->p2p_intra_bss) ||
    946 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
    947 					 wpa_s->conf->p2p_group_idle) ||
    948 	    !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
    949 					 wpa_s->conf->disassoc_low_ack) ||
    950 	    !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
    951 				       wpa_s->conf->p2p_no_group_iface) ||
    952 	    !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
    953 					 wpa_s->conf->p2p_search_delay) ||
    954 	    !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
    955 	    !dbus_message_iter_close_container(iter, &variant_iter))
    956 		goto err_no_mem;
    957 
    958 	return TRUE;
    959 
    960 err_no_mem:
    961 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
    962 	return FALSE;
    963 }
    964 
    965 
    966 dbus_bool_t wpas_dbus_setter_p2p_device_config(
    967 	const struct wpa_dbus_property_desc *property_desc,
    968 	DBusMessageIter *iter, DBusError *error, void *user_data)
    969 {
    970 	struct wpa_supplicant *wpa_s = user_data;
    971 	DBusMessageIter variant_iter, iter_dict;
    972 	struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
    973 	unsigned int i;
    974 
    975 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
    976 		return FALSE;
    977 
    978 	wpa_s = wpa_s->global->p2p_init_wpa_s;
    979 
    980 	dbus_message_iter_recurse(iter, &variant_iter);
    981 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
    982 		return FALSE;
    983 
    984 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
    985 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
    986 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
    987 					     "invalid message format");
    988 			return FALSE;
    989 		}
    990 
    991 		if (os_strcmp(entry.key, "DeviceName") == 0) {
    992 			char *devname;
    993 
    994 			if (entry.type != DBUS_TYPE_STRING ||
    995 			    os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
    996 				goto error;
    997 
    998 			devname = os_strdup(entry.str_value);
    999 			if (devname == NULL)
   1000 				goto err_no_mem_clear;
   1001 
   1002 			os_free(wpa_s->conf->device_name);
   1003 			wpa_s->conf->device_name = devname;
   1004 
   1005 			wpa_s->conf->changed_parameters |=
   1006 				CFG_CHANGED_DEVICE_NAME;
   1007 		} else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
   1008 			if (entry.type != DBUS_TYPE_ARRAY ||
   1009 			    entry.array_type != DBUS_TYPE_BYTE ||
   1010 			    entry.array_len != WPS_DEV_TYPE_LEN)
   1011 				goto error;
   1012 
   1013 			os_memcpy(wpa_s->conf->device_type,
   1014 				  entry.bytearray_value,
   1015 				  WPS_DEV_TYPE_LEN);
   1016 			wpa_s->conf->changed_parameters |=
   1017 				CFG_CHANGED_DEVICE_TYPE;
   1018 		} else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
   1019 			if (entry.type != DBUS_TYPE_ARRAY ||
   1020 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
   1021 			    entry.array_len > MAX_SEC_DEVICE_TYPES)
   1022 				goto error;
   1023 
   1024 			for (i = 0; i < entry.array_len; i++)
   1025 				if (wpabuf_len(entry.binarray_value[i]) !=
   1026 				    WPS_DEV_TYPE_LEN)
   1027 					goto err_no_mem_clear;
   1028 			for (i = 0; i < entry.array_len; i++)
   1029 				os_memcpy(wpa_s->conf->sec_device_type[i],
   1030 					  wpabuf_head(entry.binarray_value[i]),
   1031 					  WPS_DEV_TYPE_LEN);
   1032 			wpa_s->conf->num_sec_device_types = entry.array_len;
   1033 			wpa_s->conf->changed_parameters |=
   1034 					CFG_CHANGED_SEC_DEVICE_TYPE;
   1035 		} else if (os_strcmp(entry.key, "VendorExtension") == 0) {
   1036 			if (entry.type != DBUS_TYPE_ARRAY ||
   1037 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
   1038 			    (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
   1039 				goto error;
   1040 
   1041 			wpa_s->conf->changed_parameters |=
   1042 				CFG_CHANGED_VENDOR_EXTENSION;
   1043 
   1044 			for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
   1045 				wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
   1046 				if (i < entry.array_len) {
   1047 					wpa_s->conf->wps_vendor_ext[i] =
   1048 						entry.binarray_value[i];
   1049 					entry.binarray_value[i] = NULL;
   1050 				} else
   1051 					wpa_s->conf->wps_vendor_ext[i] = NULL;
   1052 			}
   1053 		} else if (os_strcmp(entry.key, "GOIntent") == 0 &&
   1054 			   entry.type == DBUS_TYPE_UINT32 &&
   1055 			   (entry.uint32_value <= 15))
   1056 			wpa_s->conf->p2p_go_intent = entry.uint32_value;
   1057 		else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
   1058 			 entry.type == DBUS_TYPE_BOOLEAN)
   1059 			wpa_s->conf->persistent_reconnect = entry.bool_value;
   1060 		else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
   1061 			 entry.type == DBUS_TYPE_UINT32) {
   1062 			wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
   1063 			wpa_s->conf->changed_parameters |=
   1064 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
   1065 		} else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
   1066 			   entry.type == DBUS_TYPE_UINT32) {
   1067 			wpa_s->conf->p2p_listen_channel = entry.uint32_value;
   1068 			wpa_s->conf->changed_parameters |=
   1069 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
   1070 		} else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
   1071 			   entry.type == DBUS_TYPE_UINT32) {
   1072 			wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
   1073 			wpa_s->conf->changed_parameters |=
   1074 				CFG_CHANGED_P2P_OPER_CHANNEL;
   1075 		} else if (os_strcmp(entry.key, "OperChannel") == 0 &&
   1076 			   entry.type == DBUS_TYPE_UINT32) {
   1077 			wpa_s->conf->p2p_oper_channel = entry.uint32_value;
   1078 			wpa_s->conf->changed_parameters |=
   1079 				CFG_CHANGED_P2P_OPER_CHANNEL;
   1080 		} else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
   1081 			char *postfix;
   1082 
   1083 			if (entry.type != DBUS_TYPE_STRING)
   1084 				goto error;
   1085 
   1086 			postfix = os_strdup(entry.str_value);
   1087 			if (!postfix)
   1088 				goto err_no_mem_clear;
   1089 
   1090 			os_free(wpa_s->conf->p2p_ssid_postfix);
   1091 			wpa_s->conf->p2p_ssid_postfix = postfix;
   1092 
   1093 			wpa_s->conf->changed_parameters |=
   1094 					CFG_CHANGED_P2P_SSID_POSTFIX;
   1095 		} else if (os_strcmp(entry.key, "IntraBss") == 0 &&
   1096 			   entry.type == DBUS_TYPE_BOOLEAN) {
   1097 			wpa_s->conf->p2p_intra_bss = entry.bool_value;
   1098 			wpa_s->conf->changed_parameters |=
   1099 				CFG_CHANGED_P2P_INTRA_BSS;
   1100 		} else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
   1101 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
   1102 				goto error;
   1103 			os_memcpy(wpa_s->conf->ip_addr_go,
   1104 				  entry.bytearray_value, 4);
   1105 		} else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
   1106 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
   1107 				goto error;
   1108 			os_memcpy(wpa_s->conf->ip_addr_mask,
   1109 				  entry.bytearray_value, 4);
   1110 		} else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
   1111 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
   1112 				goto error;
   1113 			os_memcpy(wpa_s->conf->ip_addr_start,
   1114 				  entry.bytearray_value, 4);
   1115 		} else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
   1116 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
   1117 				goto error;
   1118 			os_memcpy(wpa_s->conf->ip_addr_end,
   1119 				  entry.bytearray_value, 4);
   1120 		} else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
   1121 			   entry.type == DBUS_TYPE_UINT32)
   1122 			wpa_s->conf->p2p_group_idle = entry.uint32_value;
   1123 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
   1124 			 entry.type == DBUS_TYPE_UINT32)
   1125 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
   1126 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
   1127 			 entry.type == DBUS_TYPE_BOOLEAN)
   1128 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
   1129 		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
   1130 			 entry.type == DBUS_TYPE_UINT32)
   1131 			wpa_s->conf->p2p_search_delay = entry.uint32_value;
   1132 		else
   1133 			goto error;
   1134 
   1135 		wpa_dbus_dict_entry_clear(&entry);
   1136 	}
   1137 
   1138 	if (wpa_s->conf->changed_parameters) {
   1139 		/* Some changed parameters requires to update config*/
   1140 		wpa_supplicant_update_config(wpa_s);
   1141 	}
   1142 
   1143 	return TRUE;
   1144 
   1145  error:
   1146 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
   1147 			     "invalid message format");
   1148 	wpa_dbus_dict_entry_clear(&entry);
   1149 	return FALSE;
   1150 
   1151  err_no_mem_clear:
   1152 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1153 	wpa_dbus_dict_entry_clear(&entry);
   1154 	return FALSE;
   1155 }
   1156 
   1157 
   1158 dbus_bool_t wpas_dbus_getter_p2p_peers(
   1159 	const struct wpa_dbus_property_desc *property_desc,
   1160 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1161 {
   1162 	struct wpa_supplicant *wpa_s = user_data;
   1163 	struct p2p_data *p2p = wpa_s->global->p2p;
   1164 	int next = 0, i = 0;
   1165 	int num = 0, out_of_mem = 0;
   1166 	const u8 *addr;
   1167 	const struct p2p_peer_info *peer_info = NULL;
   1168 	dbus_bool_t success = FALSE;
   1169 
   1170 	struct dl_list peer_objpath_list;
   1171 	struct peer_objpath_node {
   1172 		struct dl_list list;
   1173 		char path[WPAS_DBUS_OBJECT_PATH_MAX];
   1174 	} *node, *tmp;
   1175 
   1176 	char **peer_obj_paths = NULL;
   1177 
   1178 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
   1179 	    !wpa_s->parent->parent->dbus_new_path)
   1180 		return FALSE;
   1181 
   1182 	dl_list_init(&peer_objpath_list);
   1183 
   1184 	/* Get the first peer info */
   1185 	peer_info = p2p_get_peer_found(p2p, NULL, next);
   1186 
   1187 	/* Get next and accumulate them */
   1188 	next = 1;
   1189 	while (peer_info != NULL) {
   1190 		node = os_zalloc(sizeof(struct peer_objpath_node));
   1191 		if (!node) {
   1192 			out_of_mem = 1;
   1193 			goto error;
   1194 		}
   1195 
   1196 		addr = peer_info->p2p_device_addr;
   1197 		os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
   1198 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
   1199 			    "/" COMPACT_MACSTR,
   1200 			    wpa_s->parent->parent->dbus_new_path,
   1201 			    MAC2STR(addr));
   1202 		dl_list_add_tail(&peer_objpath_list, &node->list);
   1203 		num++;
   1204 
   1205 		peer_info = p2p_get_peer_found(p2p, addr, next);
   1206 	}
   1207 
   1208 	/*
   1209 	 * Now construct the peer object paths in a form suitable for
   1210 	 * array_property_getter helper below.
   1211 	 */
   1212 	peer_obj_paths = os_calloc(num, sizeof(char *));
   1213 
   1214 	if (!peer_obj_paths) {
   1215 		out_of_mem = 1;
   1216 		goto error;
   1217 	}
   1218 
   1219 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
   1220 			      struct peer_objpath_node, list)
   1221 		peer_obj_paths[i++] = node->path;
   1222 
   1223 	success = wpas_dbus_simple_array_property_getter(iter,
   1224 							 DBUS_TYPE_OBJECT_PATH,
   1225 							 peer_obj_paths, num,
   1226 							 error);
   1227 
   1228 error:
   1229 	if (peer_obj_paths)
   1230 		os_free(peer_obj_paths);
   1231 
   1232 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
   1233 			      struct peer_objpath_node, list) {
   1234 		dl_list_del(&node->list);
   1235 		os_free(node);
   1236 	}
   1237 	if (out_of_mem)
   1238 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1239 
   1240 	return success;
   1241 }
   1242 
   1243 
   1244 enum wpas_p2p_role {
   1245 	WPAS_P2P_ROLE_DEVICE,
   1246 	WPAS_P2P_ROLE_GO,
   1247 	WPAS_P2P_ROLE_CLIENT,
   1248 };
   1249 
   1250 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
   1251 {
   1252 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   1253 
   1254 	if (!ssid)
   1255 		return WPAS_P2P_ROLE_DEVICE;
   1256 	if (wpa_s->wpa_state != WPA_COMPLETED)
   1257 		return WPAS_P2P_ROLE_DEVICE;
   1258 
   1259 	switch (ssid->mode) {
   1260 	case WPAS_MODE_P2P_GO:
   1261 	case WPAS_MODE_P2P_GROUP_FORMATION:
   1262 		return WPAS_P2P_ROLE_GO;
   1263 	case WPAS_MODE_INFRA:
   1264 		if (ssid->p2p_group)
   1265 			return WPAS_P2P_ROLE_CLIENT;
   1266 		return WPAS_P2P_ROLE_DEVICE;
   1267 	default:
   1268 		return WPAS_P2P_ROLE_DEVICE;
   1269 	}
   1270 }
   1271 
   1272 
   1273 dbus_bool_t wpas_dbus_getter_p2p_role(
   1274 	const struct wpa_dbus_property_desc *property_desc,
   1275 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1276 {
   1277 	struct wpa_supplicant *wpa_s = user_data;
   1278 	char *str;
   1279 
   1280 	switch (wpas_get_p2p_role(wpa_s)) {
   1281 	case WPAS_P2P_ROLE_GO:
   1282 		str = "GO";
   1283 		break;
   1284 	case WPAS_P2P_ROLE_CLIENT:
   1285 		str = "client";
   1286 		break;
   1287 	default:
   1288 		str = "device";
   1289 		break;
   1290 	}
   1291 
   1292 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
   1293 						error);
   1294 }
   1295 
   1296 
   1297 dbus_bool_t wpas_dbus_getter_p2p_group(
   1298 	const struct wpa_dbus_property_desc *property_desc,
   1299 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1300 {
   1301 	struct wpa_supplicant *wpa_s = user_data;
   1302 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
   1303 	char *dbus_groupobj_path = path_buf;
   1304 
   1305 	if (wpa_s->dbus_groupobj_path == NULL)
   1306 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1307 			    "/");
   1308 	else
   1309 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1310 			    "%s", wpa_s->dbus_groupobj_path);
   1311 
   1312 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
   1313 						&dbus_groupobj_path, error);
   1314 }
   1315 
   1316 
   1317 dbus_bool_t wpas_dbus_getter_p2p_peergo(
   1318 	const struct wpa_dbus_property_desc *property_desc,
   1319 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1320 {
   1321 	struct wpa_supplicant *wpa_s = user_data;
   1322 	char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1323 
   1324 	if (!wpa_s->parent->parent->dbus_new_path)
   1325 		return FALSE;
   1326 
   1327 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
   1328 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
   1329 	else
   1330 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1331 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1332 			    COMPACT_MACSTR,
   1333 			    wpa_s->parent->parent->dbus_new_path,
   1334 			    MAC2STR(wpa_s->go_dev_addr));
   1335 
   1336 	path = go_peer_obj_path;
   1337 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
   1338 						&path, error);
   1339 }
   1340 
   1341 
   1342 /*
   1343  * Peer object properties accessor methods
   1344  */
   1345 
   1346 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
   1347 	const struct wpa_dbus_property_desc *property_desc,
   1348 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1349 {
   1350 	struct peer_handler_args *peer_args = user_data;
   1351 	const struct p2p_peer_info *info;
   1352 	char *tmp;
   1353 
   1354 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
   1355 		return FALSE;
   1356 
   1357 	/* get the peer info */
   1358 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1359 				  peer_args->p2p_device_addr, 0);
   1360 	if (info == NULL) {
   1361 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1362 			       "failed to find peer");
   1363 		return FALSE;
   1364 	}
   1365 
   1366 	tmp = os_strdup(info->device_name);
   1367 	if (!tmp) {
   1368 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1369 		return FALSE;
   1370 	}
   1371 
   1372 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
   1373 					      error)) {
   1374 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1375 		os_free(tmp);
   1376 		return FALSE;
   1377 	}
   1378 
   1379 	os_free(tmp);
   1380 	return TRUE;
   1381 }
   1382 
   1383 
   1384 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
   1385 	const struct wpa_dbus_property_desc *property_desc,
   1386 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1387 {
   1388 	struct peer_handler_args *peer_args = user_data;
   1389 	const struct p2p_peer_info *info;
   1390 	char *tmp;
   1391 
   1392 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
   1393 		return FALSE;
   1394 
   1395 	/* get the peer info */
   1396 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1397 				  peer_args->p2p_device_addr, 0);
   1398 	if (info == NULL) {
   1399 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
   1400 		return FALSE;
   1401 	}
   1402 
   1403 	tmp = os_strdup(info->manufacturer);
   1404 	if (!tmp) {
   1405 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1406 		return FALSE;
   1407 	}
   1408 
   1409 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
   1410 					      error)) {
   1411 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1412 		os_free(tmp);
   1413 		return FALSE;
   1414 	}
   1415 
   1416 	os_free(tmp);
   1417 	return TRUE;
   1418 }
   1419 
   1420 
   1421 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
   1422 	const struct wpa_dbus_property_desc *property_desc,
   1423 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1424 {
   1425 	struct peer_handler_args *peer_args = user_data;
   1426 	const struct p2p_peer_info *info;
   1427 	char *tmp;
   1428 
   1429 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
   1430 		return FALSE;
   1431 
   1432 	/* get the peer info */
   1433 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1434 				  peer_args->p2p_device_addr, 0);
   1435 	if (info == NULL) {
   1436 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
   1437 		return FALSE;
   1438 	}
   1439 
   1440 	tmp = os_strdup(info->model_name);
   1441 	if (!tmp) {
   1442 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1443 		return FALSE;
   1444 	}
   1445 
   1446 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
   1447 					      error)) {
   1448 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1449 		os_free(tmp);
   1450 		return FALSE;
   1451 	}
   1452 
   1453 	os_free(tmp);
   1454 	return TRUE;
   1455 }
   1456 
   1457 
   1458 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
   1459 	const struct wpa_dbus_property_desc *property_desc,
   1460 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1461 {
   1462 	struct peer_handler_args *peer_args = user_data;
   1463 	const struct p2p_peer_info *info;
   1464 	char *tmp;
   1465 
   1466 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
   1467 		return FALSE;
   1468 
   1469 	/* get the peer info */
   1470 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1471 				  peer_args->p2p_device_addr, 0);
   1472 	if (info == NULL) {
   1473 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
   1474 		return FALSE;
   1475 	}
   1476 
   1477 	tmp = os_strdup(info->model_number);
   1478 	if (!tmp) {
   1479 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1480 		return FALSE;
   1481 	}
   1482 
   1483 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
   1484 					      error)) {
   1485 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1486 		os_free(tmp);
   1487 		return FALSE;
   1488 	}
   1489 
   1490 	os_free(tmp);
   1491 	return TRUE;
   1492 }
   1493 
   1494 
   1495 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
   1496 	const struct wpa_dbus_property_desc *property_desc,
   1497 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1498 {
   1499 	struct peer_handler_args *peer_args = user_data;
   1500 	const struct p2p_peer_info *info;
   1501 	char *tmp;
   1502 
   1503 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
   1504 		return FALSE;
   1505 
   1506 	/* get the peer info */
   1507 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1508 				  peer_args->p2p_device_addr, 0);
   1509 	if (info == NULL) {
   1510 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
   1511 		return FALSE;
   1512 	}
   1513 
   1514 	tmp = os_strdup(info->serial_number);
   1515 	if (!tmp) {
   1516 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1517 		return FALSE;
   1518 	}
   1519 
   1520 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
   1521 					      error)) {
   1522 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1523 		os_free(tmp);
   1524 		return FALSE;
   1525 	}
   1526 
   1527 	os_free(tmp);
   1528 	return TRUE;
   1529 }
   1530 
   1531 
   1532 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
   1533 	const struct wpa_dbus_property_desc *property_desc,
   1534 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1535 {
   1536 	struct peer_handler_args *peer_args = user_data;
   1537 	const struct p2p_peer_info *info;
   1538 
   1539 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1540 				  peer_args->p2p_device_addr, 0);
   1541 	if (info == NULL) {
   1542 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1543 			       "failed to find peer");
   1544 		return FALSE;
   1545 	}
   1546 
   1547 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   1548 						    (char *)
   1549 						    info->pri_dev_type,
   1550 						    WPS_DEV_TYPE_LEN, error)) {
   1551 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1552 		return FALSE;
   1553 	}
   1554 
   1555 	return TRUE;
   1556 }
   1557 
   1558 
   1559 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
   1560 	const struct wpa_dbus_property_desc *property_desc,
   1561 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1562 {
   1563 	struct peer_handler_args *peer_args = user_data;
   1564 	const struct p2p_peer_info *info;
   1565 
   1566 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1567 				  peer_args->p2p_device_addr, 0);
   1568 	if (info == NULL) {
   1569 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1570 			       "failed to find peer");
   1571 		return FALSE;
   1572 	}
   1573 
   1574 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
   1575 					      &info->config_methods, error)) {
   1576 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1577 		return FALSE;
   1578 	}
   1579 
   1580 	return TRUE;
   1581 }
   1582 
   1583 
   1584 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
   1585 	const struct wpa_dbus_property_desc *property_desc,
   1586 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1587 {
   1588 	struct peer_handler_args *peer_args = user_data;
   1589 	const struct p2p_peer_info *info;
   1590 
   1591 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1592 				  peer_args->p2p_device_addr, 0);
   1593 	if (info == NULL) {
   1594 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1595 			       "failed to find peer");
   1596 		return FALSE;
   1597 	}
   1598 
   1599 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
   1600 					      &info->level, error)) {
   1601 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1602 		return FALSE;
   1603 	}
   1604 
   1605 	return TRUE;
   1606 }
   1607 
   1608 
   1609 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
   1610 	const struct wpa_dbus_property_desc *property_desc,
   1611 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1612 {
   1613 	struct peer_handler_args *peer_args = user_data;
   1614 	const struct p2p_peer_info *info;
   1615 
   1616 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1617 				  peer_args->p2p_device_addr, 0);
   1618 	if (info == NULL) {
   1619 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1620 			       "failed to find peer");
   1621 		return FALSE;
   1622 	}
   1623 
   1624 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
   1625 					      &info->dev_capab, error)) {
   1626 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1627 		return FALSE;
   1628 	}
   1629 
   1630 	return TRUE;
   1631 }
   1632 
   1633 
   1634 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
   1635 	const struct wpa_dbus_property_desc *property_desc,
   1636 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1637 {
   1638 	struct peer_handler_args *peer_args = user_data;
   1639 	const struct p2p_peer_info *info;
   1640 
   1641 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1642 				  peer_args->p2p_device_addr, 0);
   1643 	if (info == NULL) {
   1644 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1645 			       "failed to find peer");
   1646 		return FALSE;
   1647 	}
   1648 
   1649 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
   1650 					      &info->group_capab, error)) {
   1651 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1652 		return FALSE;
   1653 	}
   1654 
   1655 	return TRUE;
   1656 }
   1657 
   1658 
   1659 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
   1660 	const struct wpa_dbus_property_desc *property_desc,
   1661 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1662 {
   1663 	struct peer_handler_args *peer_args = user_data;
   1664 	const struct p2p_peer_info *info;
   1665 	DBusMessageIter variant_iter, array_iter;
   1666 
   1667 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1668 				  peer_args->p2p_device_addr, 0);
   1669 	if (info == NULL) {
   1670 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
   1671 		return FALSE;
   1672 	}
   1673 
   1674 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
   1675 					      DBUS_TYPE_ARRAY_AS_STRING
   1676 					      DBUS_TYPE_ARRAY_AS_STRING
   1677 					      DBUS_TYPE_BYTE_AS_STRING,
   1678 					      &variant_iter) ||
   1679 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
   1680 					      DBUS_TYPE_ARRAY_AS_STRING
   1681 					      DBUS_TYPE_BYTE_AS_STRING,
   1682 					      &array_iter)) {
   1683 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1684 			       "%s: failed to construct message 1", __func__);
   1685 		return FALSE;
   1686 	}
   1687 
   1688 	if (info->wps_sec_dev_type_list_len) {
   1689 		const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
   1690 		int num_sec_device_types =
   1691 			info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
   1692 		int i;
   1693 		DBusMessageIter inner_array_iter;
   1694 
   1695 		for (i = 0; i < num_sec_device_types; i++) {
   1696 			if (!dbus_message_iter_open_container(
   1697 				    &array_iter, DBUS_TYPE_ARRAY,
   1698 				    DBUS_TYPE_BYTE_AS_STRING,
   1699 				    &inner_array_iter) ||
   1700 			    !dbus_message_iter_append_fixed_array(
   1701 				    &inner_array_iter, DBUS_TYPE_BYTE,
   1702 				    &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
   1703 			    !dbus_message_iter_close_container(
   1704 				    &array_iter, &inner_array_iter)) {
   1705 				dbus_set_error(error, DBUS_ERROR_FAILED,
   1706 					       "%s: failed to construct message 2 (%d)",
   1707 					       __func__, i);
   1708 				return FALSE;
   1709 			}
   1710 
   1711 			sec_dev_type_list += WPS_DEV_TYPE_LEN;
   1712 		}
   1713 	}
   1714 
   1715 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
   1716 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
   1717 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1718 			       "%s: failed to construct message 3", __func__);
   1719 		return FALSE;
   1720 	}
   1721 
   1722 	return TRUE;
   1723 }
   1724 
   1725 
   1726 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
   1727 	const struct wpa_dbus_property_desc *property_desc,
   1728 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1729 {
   1730 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
   1731 	unsigned int i, num = 0;
   1732 	struct peer_handler_args *peer_args = user_data;
   1733 	const struct p2p_peer_info *info;
   1734 
   1735 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1736 				  peer_args->p2p_device_addr, 0);
   1737 	if (info == NULL) {
   1738 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1739 			       "failed to find peer");
   1740 		return FALSE;
   1741 	}
   1742 
   1743 	/* Add WPS vendor extensions attribute */
   1744 	os_memset(vendor_extension, 0, sizeof(vendor_extension));
   1745 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
   1746 		if (info->wps_vendor_ext[i] == NULL)
   1747 			continue;
   1748 		vendor_extension[num] = info->wps_vendor_ext[i];
   1749 		num++;
   1750 	}
   1751 
   1752 	if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
   1753 							  vendor_extension,
   1754 							  num, error))
   1755 		return FALSE;
   1756 
   1757 	return TRUE;
   1758 }
   1759 
   1760 
   1761 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
   1762 	const struct wpa_dbus_property_desc *property_desc,
   1763 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1764 {
   1765 	struct peer_handler_args *peer_args = user_data;
   1766 	const struct p2p_peer_info *info;
   1767 
   1768 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1769 				  peer_args->p2p_device_addr, 0);
   1770 	if (info == NULL) {
   1771 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1772 			       "failed to find peer");
   1773 		return FALSE;
   1774 	}
   1775 
   1776 	if (info->wfd_subelems == NULL)
   1777 		return wpas_dbus_simple_array_property_getter(iter,
   1778 							      DBUS_TYPE_BYTE,
   1779 							      NULL, 0, error);
   1780 
   1781 	return wpas_dbus_simple_array_property_getter(
   1782 		iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
   1783 		info->wfd_subelems->used, error);
   1784 }
   1785 
   1786 
   1787 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
   1788 	const struct wpa_dbus_property_desc *property_desc,
   1789 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1790 {
   1791 	struct peer_handler_args *peer_args = user_data;
   1792 	const struct p2p_peer_info *info;
   1793 
   1794 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1795 				  peer_args->p2p_device_addr, 0);
   1796 	if (info == NULL) {
   1797 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1798 			       "failed to find peer");
   1799 		return FALSE;
   1800 	}
   1801 
   1802 	return wpas_dbus_simple_array_property_getter(
   1803 		iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
   1804 		ETH_ALEN, error);
   1805 }
   1806 
   1807 
   1808 struct peer_group_data {
   1809 	struct wpa_supplicant *wpa_s;
   1810 	const struct p2p_peer_info *info;
   1811 	char **paths;
   1812 	unsigned int nb_paths;
   1813 	int error;
   1814 };
   1815 
   1816 
   1817 static int match_group_where_peer_is_client(struct p2p_group *group,
   1818 					    void *user_data)
   1819 {
   1820 	struct peer_group_data *data = user_data;
   1821 	const struct p2p_group_config *cfg;
   1822 	struct wpa_supplicant *wpa_s_go;
   1823 	char **paths;
   1824 
   1825 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
   1826 		return 1;
   1827 
   1828 	cfg = p2p_group_get_config(group);
   1829 
   1830 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
   1831 					 cfg->ssid_len);
   1832 	if (wpa_s_go == NULL)
   1833 		return 1;
   1834 
   1835 	paths = os_realloc_array(data->paths, data->nb_paths + 1,
   1836 				 sizeof(char *));
   1837 	if (paths == NULL)
   1838 		goto out_of_memory;
   1839 
   1840 	data->paths = paths;
   1841 	data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
   1842 	data->nb_paths++;
   1843 
   1844 	return 1;
   1845 
   1846 out_of_memory:
   1847 	data->error = ENOMEM;
   1848 	return 0;
   1849 }
   1850 
   1851 
   1852 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
   1853 	const struct wpa_dbus_property_desc *property_desc,
   1854 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1855 {
   1856 	struct peer_handler_args *peer_args = user_data;
   1857 	const struct p2p_peer_info *info;
   1858 	struct peer_group_data data;
   1859 	struct wpa_supplicant *wpa_s, *wpa_s_go;
   1860 	dbus_bool_t success = FALSE;
   1861 
   1862 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
   1863 				  peer_args->p2p_device_addr, 0);
   1864 	if (info == NULL) {
   1865 		dbus_set_error(error, DBUS_ERROR_FAILED,
   1866 			       "failed to find peer");
   1867 		return FALSE;
   1868 	}
   1869 
   1870 	os_memset(&data, 0, sizeof(data));
   1871 
   1872 	wpa_s = peer_args->wpa_s;
   1873 	wpa_s = wpa_s->global->p2p_init_wpa_s;
   1874 
   1875 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
   1876 	if (wpa_s_go) {
   1877 		data.paths = os_calloc(1, sizeof(char *));
   1878 		if (data.paths == NULL)
   1879 			goto out_of_memory;
   1880 		data.paths[0] = wpa_s_go->dbus_groupobj_path;
   1881 		data.nb_paths = 1;
   1882 	}
   1883 
   1884 	data.wpa_s = peer_args->wpa_s;
   1885 	data.info = info;
   1886 
   1887 	p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
   1888 			       match_group_where_peer_is_client, &data);
   1889 	if (data.error)
   1890 		goto out_of_memory;
   1891 
   1892 	if (data.paths == NULL) {
   1893 		return wpas_dbus_simple_array_property_getter(
   1894 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
   1895 	}
   1896 
   1897 	success = wpas_dbus_simple_array_property_getter(iter,
   1898 							 DBUS_TYPE_OBJECT_PATH,
   1899 							 data.paths,
   1900 							 data.nb_paths, error);
   1901 	goto out;
   1902 
   1903 out_of_memory:
   1904 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1905 out:
   1906 	os_free(data.paths);
   1907 	return success;
   1908 }
   1909 
   1910 
   1911 /**
   1912  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
   1913  * @iter: Pointer to incoming dbus message iter
   1914  * @error: Location to store error on failure
   1915  * @user_data: Function specific data
   1916  * Returns: TRUE on success, FALSE on failure
   1917  *
   1918  * Getter for "PersistentGroups" property.
   1919  */
   1920 dbus_bool_t wpas_dbus_getter_persistent_groups(
   1921 	const struct wpa_dbus_property_desc *property_desc,
   1922 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1923 {
   1924 	struct wpa_supplicant *wpa_s = user_data;
   1925 	struct wpa_ssid *ssid;
   1926 	char **paths;
   1927 	unsigned int i = 0, num = 0;
   1928 	dbus_bool_t success = FALSE;
   1929 
   1930 	wpa_s = wpa_s->global->p2p_init_wpa_s;
   1931 	if (!wpa_s->parent->dbus_new_path)
   1932 		return FALSE;
   1933 
   1934 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
   1935 		if (network_is_persistent_group(ssid))
   1936 			num++;
   1937 
   1938 	paths = os_calloc(num, sizeof(char *));
   1939 	if (!paths) {
   1940 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   1941 		return FALSE;
   1942 	}
   1943 
   1944 	/* Loop through configured networks and append object path of each */
   1945 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
   1946 		if (!network_is_persistent_group(ssid))
   1947 			continue;
   1948 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   1949 		if (paths[i] == NULL) {
   1950 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
   1951 					     "no memory");
   1952 			goto out;
   1953 		}
   1954 		/* Construct the object path for this network. */
   1955 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
   1956 			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
   1957 			    wpa_s->parent->dbus_new_path, ssid->id);
   1958 	}
   1959 
   1960 	success = wpas_dbus_simple_array_property_getter(iter,
   1961 							 DBUS_TYPE_OBJECT_PATH,
   1962 							 paths, num, error);
   1963 
   1964 out:
   1965 	while (i)
   1966 		os_free(paths[--i]);
   1967 	os_free(paths);
   1968 	return success;
   1969 }
   1970 
   1971 
   1972 /**
   1973  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
   1974  *	group
   1975  * @iter: Pointer to incoming dbus message iter
   1976  * @error: Location to store error on failure
   1977  * @user_data: Function specific data
   1978  * Returns: TRUE on success, FALSE on failure
   1979  *
   1980  * Getter for "Properties" property of a persistent group.
   1981  */
   1982 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
   1983 	const struct wpa_dbus_property_desc *property_desc,
   1984 	DBusMessageIter *iter, DBusError *error, void *user_data)
   1985 {
   1986 	struct network_handler_args *net = user_data;
   1987 
   1988 	/* Leveraging the fact that persistent group object is still
   1989 	 * represented in same manner as network within.
   1990 	 */
   1991 	return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
   1992 }
   1993 
   1994 
   1995 /**
   1996  * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
   1997  *	group
   1998  * @iter: Pointer to incoming dbus message iter
   1999  * @error: Location to store error on failure
   2000  * @user_data: Function specific data
   2001  * Returns: TRUE on success, FALSE on failure
   2002  *
   2003  * Setter for "Properties" property of a persistent group.
   2004  */
   2005 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
   2006 	const struct wpa_dbus_property_desc *property_desc,
   2007 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2008 {
   2009 	struct network_handler_args *net = user_data;
   2010 	struct wpa_ssid *ssid = net->ssid;
   2011 	DBusMessageIter	variant_iter;
   2012 
   2013 	/*
   2014 	 * Leveraging the fact that persistent group object is still
   2015 	 * represented in same manner as network within.
   2016 	 */
   2017 	dbus_message_iter_recurse(iter, &variant_iter);
   2018 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
   2019 }
   2020 
   2021 
   2022 /**
   2023  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
   2024  *	persistent_group
   2025  * @message: Pointer to incoming dbus message
   2026  * @wpa_s: wpa_supplicant structure for a network interface
   2027  * Returns: A dbus message containing the object path of the new
   2028  * persistent group
   2029  *
   2030  * Handler function for "AddPersistentGroup" method call of a P2P Device
   2031  * interface.
   2032  */
   2033 DBusMessage * wpas_dbus_handler_add_persistent_group(
   2034 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2035 {
   2036 	DBusMessage *reply = NULL;
   2037 	DBusMessageIter	iter;
   2038 	struct wpa_ssid *ssid = NULL;
   2039 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
   2040 	DBusError error;
   2041 
   2042 	dbus_message_iter_init(message, &iter);
   2043 
   2044 	wpa_s = wpa_s->global->p2p_init_wpa_s;
   2045 	if (wpa_s->parent->dbus_new_path)
   2046 		ssid = wpa_config_add_network(wpa_s->conf);
   2047 	if (ssid == NULL) {
   2048 		wpa_printf(MSG_ERROR,
   2049 			   "dbus: %s: Cannot add new persistent group",
   2050 			   __func__);
   2051 		reply = wpas_dbus_error_unknown_error(
   2052 			message,
   2053 			"wpa_supplicant could not add a persistent group on this interface.");
   2054 		goto err;
   2055 	}
   2056 
   2057 	/* Mark the ssid as being a persistent group before the notification */
   2058 	ssid->disabled = 2;
   2059 	ssid->p2p_persistent_group = 1;
   2060 	wpas_notify_persistent_group_added(wpa_s, ssid);
   2061 
   2062 	wpa_config_set_network_defaults(ssid);
   2063 
   2064 	dbus_error_init(&error);
   2065 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
   2066 		wpa_printf(MSG_DEBUG,
   2067 			   "dbus: %s: Control interface could not set persistent group properties",
   2068 			   __func__);
   2069 		reply = wpas_dbus_reply_new_from_error(
   2070 			message, &error, DBUS_ERROR_INVALID_ARGS,
   2071 			"Failed to set network properties");
   2072 		dbus_error_free(&error);
   2073 		goto err;
   2074 	}
   2075 
   2076 	/* Construct the object path for this network. */
   2077 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
   2078 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
   2079 		    wpa_s->parent->dbus_new_path, ssid->id);
   2080 
   2081 	reply = dbus_message_new_method_return(message);
   2082 	if (reply == NULL) {
   2083 		reply = wpas_dbus_error_no_memory(message);
   2084 		goto err;
   2085 	}
   2086 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
   2087 				      DBUS_TYPE_INVALID)) {
   2088 		dbus_message_unref(reply);
   2089 		reply = wpas_dbus_error_no_memory(message);
   2090 		goto err;
   2091 	}
   2092 
   2093 	return reply;
   2094 
   2095 err:
   2096 	if (ssid) {
   2097 		wpas_notify_persistent_group_removed(wpa_s, ssid);
   2098 		wpa_config_remove_network(wpa_s->conf, ssid->id);
   2099 	}
   2100 	return reply;
   2101 }
   2102 
   2103 
   2104 /**
   2105  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
   2106  *	group
   2107  * @message: Pointer to incoming dbus message
   2108  * @wpa_s: wpa_supplicant structure for a network interface
   2109  * Returns: NULL on success or dbus error on failure
   2110  *
   2111  * Handler function for "RemovePersistentGroup" method call of a P2P Device
   2112  * interface.
   2113  */
   2114 DBusMessage * wpas_dbus_handler_remove_persistent_group(
   2115 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2116 {
   2117 	DBusMessage *reply = NULL;
   2118 	const char *op;
   2119 	char *iface = NULL, *persistent_group_id;
   2120 	int id;
   2121 	struct wpa_ssid *ssid;
   2122 
   2123 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
   2124 			      DBUS_TYPE_INVALID);
   2125 
   2126 	wpa_s = wpa_s->global->p2p_init_wpa_s;
   2127 
   2128 	/*
   2129 	 * Extract the network ID and ensure the network is actually a child of
   2130 	 * this interface.
   2131 	 */
   2132 	iface = wpas_dbus_new_decompose_object_path(
   2133 		op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
   2134 		&persistent_group_id);
   2135 	if (iface == NULL || persistent_group_id == NULL ||
   2136 	    !wpa_s->parent->dbus_new_path ||
   2137 	    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
   2138 		reply = wpas_dbus_error_invalid_args(message, op);
   2139 		goto out;
   2140 	}
   2141 
   2142 	id = strtoul(persistent_group_id, NULL, 10);
   2143 	if (errno == EINVAL) {
   2144 		reply = wpas_dbus_error_invalid_args(message, op);
   2145 		goto out;
   2146 	}
   2147 
   2148 	ssid = wpa_config_get_network(wpa_s->conf, id);
   2149 	if (ssid == NULL) {
   2150 		reply = wpas_dbus_error_persistent_group_unknown(message);
   2151 		goto out;
   2152 	}
   2153 
   2154 	wpas_notify_persistent_group_removed(wpa_s, ssid);
   2155 
   2156 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
   2157 		wpa_printf(MSG_ERROR,
   2158 			   "dbus: %s: error occurred when removing persistent group %d",
   2159 			   __func__, id);
   2160 		reply = wpas_dbus_error_unknown_error(
   2161 			message,
   2162 			"error removing the specified persistent group on this interface.");
   2163 		goto out;
   2164 	}
   2165 
   2166 out:
   2167 	os_free(iface);
   2168 	return reply;
   2169 }
   2170 
   2171 
   2172 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
   2173 				    struct wpa_ssid *ssid)
   2174 {
   2175 	wpas_notify_persistent_group_removed(wpa_s, ssid);
   2176 
   2177 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
   2178 		wpa_printf(MSG_ERROR,
   2179 			   "dbus: %s: error occurred when removing persistent group %d",
   2180 			   __func__, ssid->id);
   2181 		return;
   2182 	}
   2183 }
   2184 
   2185 
   2186 /**
   2187  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
   2188  * persistent groups
   2189  * @message: Pointer to incoming dbus message
   2190  * @wpa_s: wpa_supplicant structure for a network interface
   2191  * Returns: NULL on success or dbus error on failure
   2192  *
   2193  * Handler function for "RemoveAllPersistentGroups" method call of a
   2194  * P2P Device interface.
   2195  */
   2196 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
   2197 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2198 {
   2199 	struct wpa_ssid *ssid, *next;
   2200 	struct wpa_config *config;
   2201 
   2202 	wpa_s = wpa_s->global->p2p_init_wpa_s;
   2203 
   2204 	config = wpa_s->conf;
   2205 	ssid = config->ssid;
   2206 	while (ssid) {
   2207 		next = ssid->next;
   2208 		if (network_is_persistent_group(ssid))
   2209 			remove_persistent_group(wpa_s, ssid);
   2210 		ssid = next;
   2211 	}
   2212 	return NULL;
   2213 }
   2214 
   2215 
   2216 /*
   2217  * Group object properties accessor methods
   2218  */
   2219 
   2220 dbus_bool_t wpas_dbus_getter_p2p_group_members(
   2221 	const struct wpa_dbus_property_desc *property_desc,
   2222 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2223 {
   2224 	struct wpa_supplicant *wpa_s = user_data;
   2225 	struct wpa_ssid *ssid;
   2226 	unsigned int num_members;
   2227 	char **paths;
   2228 	unsigned int i;
   2229 	void *next = NULL;
   2230 	const u8 *addr;
   2231 	dbus_bool_t success = FALSE;
   2232 
   2233 	if (!wpa_s->parent->parent->dbus_new_path)
   2234 		return FALSE;
   2235 
   2236 	/* Verify correct role for this property */
   2237 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
   2238 		return wpas_dbus_simple_array_property_getter(
   2239 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
   2240 	}
   2241 
   2242 	ssid = wpa_s->conf->ssid;
   2243 	/* At present WPAS P2P_GO mode only applicable for p2p_go */
   2244 	if (ssid->mode != WPAS_MODE_P2P_GO &&
   2245 	    ssid->mode != WPAS_MODE_AP &&
   2246 	    ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
   2247 		return FALSE;
   2248 
   2249 	num_members = p2p_get_group_num_members(wpa_s->p2p_group);
   2250 
   2251 	paths = os_calloc(num_members, sizeof(char *));
   2252 	if (!paths)
   2253 		goto out_of_memory;
   2254 
   2255 	i = 0;
   2256 	while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
   2257 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   2258 		if (!paths[i])
   2259 			goto out_of_memory;
   2260 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
   2261 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
   2262 			    "/" COMPACT_MACSTR,
   2263 			    wpa_s->parent->parent->dbus_new_path,
   2264 			    MAC2STR(addr));
   2265 		i++;
   2266 	}
   2267 
   2268 	success = wpas_dbus_simple_array_property_getter(iter,
   2269 							 DBUS_TYPE_OBJECT_PATH,
   2270 							 paths, num_members,
   2271 							 error);
   2272 
   2273 	for (i = 0; i < num_members; i++)
   2274 		os_free(paths[i]);
   2275 	os_free(paths);
   2276 	return success;
   2277 
   2278 out_of_memory:
   2279 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
   2280 	if (paths) {
   2281 		for (i = 0; i < num_members; i++)
   2282 			os_free(paths[i]);
   2283 		os_free(paths);
   2284 	}
   2285 	return FALSE;
   2286 }
   2287 
   2288 
   2289 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
   2290 	const struct wpa_dbus_property_desc *property_desc,
   2291 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2292 {
   2293 	struct wpa_supplicant *wpa_s = user_data;
   2294 
   2295 	if (wpa_s->current_ssid == NULL)
   2296 		return FALSE;
   2297 	return wpas_dbus_simple_array_property_getter(
   2298 		iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
   2299 		wpa_s->current_ssid->ssid_len, error);
   2300 }
   2301 
   2302 
   2303 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
   2304 	const struct wpa_dbus_property_desc *property_desc,
   2305 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2306 {
   2307 	struct wpa_supplicant *wpa_s = user_data;
   2308 	u8 role = wpas_get_p2p_role(wpa_s);
   2309 	u8 *p_bssid;
   2310 
   2311 	if (role == WPAS_P2P_ROLE_CLIENT) {
   2312 		if (wpa_s->current_ssid == NULL)
   2313 			return FALSE;
   2314 		p_bssid = wpa_s->current_ssid->bssid;
   2315 	} else {
   2316 		if (wpa_s->ap_iface == NULL)
   2317 			return FALSE;
   2318 		p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
   2319 	}
   2320 
   2321 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   2322 						      p_bssid, ETH_ALEN,
   2323 						      error);
   2324 }
   2325 
   2326 
   2327 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
   2328 	const struct wpa_dbus_property_desc *property_desc,
   2329 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2330 {
   2331 	struct wpa_supplicant *wpa_s = user_data;
   2332 	u16 op_freq;
   2333 	u8 role = wpas_get_p2p_role(wpa_s);
   2334 
   2335 	if (role == WPAS_P2P_ROLE_CLIENT) {
   2336 		if (wpa_s->go_params == NULL)
   2337 			return FALSE;
   2338 		op_freq = wpa_s->go_params->freq;
   2339 	} else {
   2340 		if (wpa_s->ap_iface == NULL)
   2341 			return FALSE;
   2342 		op_freq = wpa_s->ap_iface->freq;
   2343 	}
   2344 
   2345 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
   2346 						&op_freq, error);
   2347 }
   2348 
   2349 
   2350 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
   2351 	const struct wpa_dbus_property_desc *property_desc,
   2352 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2353 {
   2354 	struct wpa_supplicant *wpa_s = user_data;
   2355 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   2356 
   2357 	if (ssid == NULL)
   2358 		return FALSE;
   2359 
   2360 	return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
   2361 }
   2362 
   2363 
   2364 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
   2365 	const struct wpa_dbus_property_desc *property_desc,
   2366 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2367 {
   2368 	struct wpa_supplicant *wpa_s = user_data;
   2369 	u8 *p_psk = NULL;
   2370 	u8 psk_len = 0;
   2371 	struct wpa_ssid *ssid = wpa_s->current_ssid;
   2372 
   2373 	if (ssid == NULL)
   2374 		return FALSE;
   2375 
   2376 	if (ssid->psk_set) {
   2377 		p_psk = ssid->psk;
   2378 		psk_len = sizeof(ssid->psk);
   2379 	}
   2380 
   2381 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   2382 						      p_psk, psk_len, error);
   2383 }
   2384 
   2385 
   2386 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
   2387 	const struct wpa_dbus_property_desc *property_desc,
   2388 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2389 {
   2390 	struct wpa_supplicant *wpa_s = user_data;
   2391 	struct hostapd_data *hapd;
   2392 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
   2393 	unsigned int i, num_vendor_ext = 0;
   2394 
   2395 	os_memset(vendor_ext, 0, sizeof(vendor_ext));
   2396 
   2397 	/* Verify correct role for this property */
   2398 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
   2399 		if (wpa_s->ap_iface == NULL)
   2400 			return FALSE;
   2401 		hapd = wpa_s->ap_iface->bss[0];
   2402 
   2403 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
   2404 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
   2405 			if (hapd->conf->wps_vendor_ext[i] == NULL)
   2406 				continue;
   2407 			vendor_ext[num_vendor_ext++] =
   2408 				hapd->conf->wps_vendor_ext[i];
   2409 		}
   2410 	}
   2411 
   2412 	/* Return vendor extensions or no data */
   2413 	return wpas_dbus_simple_array_array_property_getter(iter,
   2414 							    DBUS_TYPE_BYTE,
   2415 							    vendor_ext,
   2416 							    num_vendor_ext,
   2417 							    error);
   2418 }
   2419 
   2420 
   2421 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
   2422 	const struct wpa_dbus_property_desc *property_desc,
   2423 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2424 {
   2425 	struct wpa_supplicant *wpa_s = user_data;
   2426 	DBusMessageIter variant_iter, iter_dict, array_iter, sub;
   2427 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
   2428 	unsigned int i;
   2429 	struct hostapd_data *hapd = NULL;
   2430 
   2431 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
   2432 	    wpa_s->ap_iface != NULL)
   2433 		hapd = wpa_s->ap_iface->bss[0];
   2434 	else
   2435 		return FALSE;
   2436 
   2437 	dbus_message_iter_recurse(iter, &variant_iter);
   2438 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
   2439 		return FALSE;
   2440 
   2441 	/*
   2442 	 * This is supposed to be array of bytearrays (aay), but the earlier
   2443 	 * implementation used a dict with "WPSVendorExtensions" as the key in
   2444 	 * this setter function which does not match the format used by the
   2445 	 * getter function. For backwards compatibility, allow both formats to
   2446 	 * be used in the setter.
   2447 	 */
   2448 	if (dbus_message_iter_get_element_type(&variant_iter) ==
   2449 	    DBUS_TYPE_ARRAY) {
   2450 		/* This is the proper format matching the getter */
   2451 		struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
   2452 
   2453 		dbus_message_iter_recurse(&variant_iter, &array_iter);
   2454 
   2455 		if (dbus_message_iter_get_arg_type(&array_iter) !=
   2456 		    DBUS_TYPE_ARRAY ||
   2457 		    dbus_message_iter_get_element_type(&array_iter) !=
   2458 		    DBUS_TYPE_BYTE) {
   2459 			wpa_printf(MSG_DEBUG,
   2460 				   "dbus: Not an array of array of bytes");
   2461 			return FALSE;
   2462 		}
   2463 
   2464 		i = 0;
   2465 		os_memset(vals, 0, sizeof(vals));
   2466 
   2467 		while (dbus_message_iter_get_arg_type(&array_iter) ==
   2468 		       DBUS_TYPE_ARRAY) {
   2469 			char *val;
   2470 			int len;
   2471 
   2472 			if (i == MAX_WPS_VENDOR_EXTENSIONS) {
   2473 				wpa_printf(MSG_DEBUG,
   2474 					   "dbus: Too many WPSVendorExtensions values");
   2475 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
   2476 				break;
   2477 			}
   2478 
   2479 			dbus_message_iter_recurse(&array_iter, &sub);
   2480 			dbus_message_iter_get_fixed_array(&sub, &val, &len);
   2481 			wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
   2482 				    val, len);
   2483 			vals[i] = wpabuf_alloc_copy(val, len);
   2484 			if (vals[i] == NULL) {
   2485 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
   2486 				break;
   2487 			}
   2488 			i++;
   2489 			dbus_message_iter_next(&array_iter);
   2490 		}
   2491 
   2492 		if (i > MAX_WPS_VENDOR_EXTENSIONS) {
   2493 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
   2494 				wpabuf_free(vals[i]);
   2495 			return FALSE;
   2496 		}
   2497 
   2498 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
   2499 			wpabuf_free(hapd->conf->wps_vendor_ext[i]);
   2500 			hapd->conf->wps_vendor_ext[i] = vals[i];
   2501 		}
   2502 
   2503 		hostapd_update_wps(hapd);
   2504 
   2505 		return TRUE;
   2506 	}
   2507 
   2508 	if (dbus_message_iter_get_element_type(&variant_iter) !=
   2509 	    DBUS_TYPE_DICT_ENTRY)
   2510 		return FALSE;
   2511 
   2512 	wpa_printf(MSG_DEBUG,
   2513 		   "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
   2514 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
   2515 		return FALSE;
   2516 
   2517 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2518 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
   2519 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
   2520 					     "invalid message format");
   2521 			return FALSE;
   2522 		}
   2523 
   2524 		if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
   2525 			if (entry.type != DBUS_TYPE_ARRAY ||
   2526 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
   2527 			    entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
   2528 				goto error;
   2529 
   2530 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
   2531 				wpabuf_free(hapd->conf->wps_vendor_ext[i]);
   2532 				if (i < entry.array_len) {
   2533 					hapd->conf->wps_vendor_ext[i] =
   2534 						entry.binarray_value[i];
   2535 					entry.binarray_value[i] = NULL;
   2536 				} else
   2537 					hapd->conf->wps_vendor_ext[i] = NULL;
   2538 			}
   2539 
   2540 			hostapd_update_wps(hapd);
   2541 		} else
   2542 			goto error;
   2543 
   2544 		wpa_dbus_dict_entry_clear(&entry);
   2545 	}
   2546 
   2547 	return TRUE;
   2548 
   2549 error:
   2550 	wpa_dbus_dict_entry_clear(&entry);
   2551 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
   2552 			     "invalid message format");
   2553 	return FALSE;
   2554 }
   2555 
   2556 
   2557 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
   2558 						struct wpa_supplicant *wpa_s)
   2559 {
   2560 	DBusMessageIter iter_dict;
   2561 	DBusMessage *reply = NULL;
   2562 	DBusMessageIter iter;
   2563 	struct wpa_dbus_dict_entry entry;
   2564 	int upnp = 0;
   2565 	int bonjour = 0;
   2566 	char *service = NULL;
   2567 	struct wpabuf *query = NULL;
   2568 	struct wpabuf *resp = NULL;
   2569 	u8 version = 0;
   2570 
   2571 	dbus_message_iter_init(message, &iter);
   2572 
   2573 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
   2574 		goto error;
   2575 
   2576 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2577 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2578 			goto error;
   2579 
   2580 		if (os_strcmp(entry.key, "service_type") == 0 &&
   2581 		    entry.type == DBUS_TYPE_STRING) {
   2582 			if (os_strcmp(entry.str_value, "upnp") == 0)
   2583 				upnp = 1;
   2584 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
   2585 				bonjour = 1;
   2586 			else
   2587 				goto error_clear;
   2588 		} else if (os_strcmp(entry.key, "version") == 0 &&
   2589 			   entry.type == DBUS_TYPE_INT32) {
   2590 			version = entry.uint32_value;
   2591 		} else if (os_strcmp(entry.key, "service") == 0 &&
   2592 			   entry.type == DBUS_TYPE_STRING) {
   2593 			os_free(service);
   2594 			service = os_strdup(entry.str_value);
   2595 		} else if (os_strcmp(entry.key, "query") == 0) {
   2596 			if (entry.type != DBUS_TYPE_ARRAY ||
   2597 			    entry.array_type != DBUS_TYPE_BYTE)
   2598 				goto error_clear;
   2599 			query = wpabuf_alloc_copy(
   2600 				entry.bytearray_value,
   2601 				entry.array_len);
   2602 		} else if (os_strcmp(entry.key, "response") == 0) {
   2603 			if (entry.type != DBUS_TYPE_ARRAY ||
   2604 			    entry.array_type != DBUS_TYPE_BYTE)
   2605 				goto error_clear;
   2606 			resp = wpabuf_alloc_copy(entry.bytearray_value,
   2607 						 entry.array_len);
   2608 		}
   2609 		wpa_dbus_dict_entry_clear(&entry);
   2610 	}
   2611 
   2612 	if (upnp == 1) {
   2613 		if (version <= 0 || service == NULL)
   2614 			goto error;
   2615 
   2616 		if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
   2617 			goto error;
   2618 
   2619 	} else if (bonjour == 1) {
   2620 		if (query == NULL || resp == NULL)
   2621 			goto error;
   2622 
   2623 		if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
   2624 			goto error;
   2625 		query = NULL;
   2626 		resp = NULL;
   2627 	} else
   2628 		goto error;
   2629 
   2630 	os_free(service);
   2631 	return reply;
   2632 error_clear:
   2633 	wpa_dbus_dict_entry_clear(&entry);
   2634 error:
   2635 	os_free(service);
   2636 	wpabuf_free(query);
   2637 	wpabuf_free(resp);
   2638 	return wpas_dbus_error_invalid_args(message, NULL);
   2639 }
   2640 
   2641 
   2642 DBusMessage * wpas_dbus_handler_p2p_delete_service(
   2643 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2644 {
   2645 	DBusMessageIter iter_dict;
   2646 	DBusMessage *reply = NULL;
   2647 	DBusMessageIter iter;
   2648 	struct wpa_dbus_dict_entry entry;
   2649 	int upnp = 0;
   2650 	int bonjour = 0;
   2651 	int ret = 0;
   2652 	char *service = NULL;
   2653 	struct wpabuf *query = NULL;
   2654 	u8 version = 0;
   2655 
   2656 	dbus_message_iter_init(message, &iter);
   2657 
   2658 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
   2659 		goto error;
   2660 
   2661 	if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2662 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2663 			goto error;
   2664 
   2665 		if (os_strcmp(entry.key, "service_type") == 0 &&
   2666 		    entry.type == DBUS_TYPE_STRING) {
   2667 			if (os_strcmp(entry.str_value, "upnp") == 0)
   2668 				upnp = 1;
   2669 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
   2670 				bonjour = 1;
   2671 			else
   2672 				goto error_clear;
   2673 			wpa_dbus_dict_entry_clear(&entry);
   2674 		}
   2675 	}
   2676 	if (upnp == 1) {
   2677 		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2678 			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2679 				goto error;
   2680 			if (os_strcmp(entry.key, "version") == 0 &&
   2681 			    entry.type == DBUS_TYPE_INT32)
   2682 				version = entry.uint32_value;
   2683 			else if (os_strcmp(entry.key, "service") == 0 &&
   2684 				 entry.type == DBUS_TYPE_STRING) {
   2685 				os_free(service);
   2686 				service = os_strdup(entry.str_value);
   2687 			} else
   2688 				goto error_clear;
   2689 
   2690 			wpa_dbus_dict_entry_clear(&entry);
   2691 		}
   2692 
   2693 		if (version <= 0 || service == NULL)
   2694 			goto error;
   2695 
   2696 		ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
   2697 		if (ret != 0)
   2698 			goto error;
   2699 	} else if (bonjour == 1) {
   2700 		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2701 			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2702 				goto error;
   2703 
   2704 			if (os_strcmp(entry.key, "query") == 0) {
   2705 				if (entry.type != DBUS_TYPE_ARRAY ||
   2706 				    entry.array_type != DBUS_TYPE_BYTE)
   2707 					goto error_clear;
   2708 				wpabuf_free(query);
   2709 				query = wpabuf_alloc_copy(
   2710 					entry.bytearray_value,
   2711 					entry.array_len);
   2712 			} else
   2713 				goto error_clear;
   2714 
   2715 			wpa_dbus_dict_entry_clear(&entry);
   2716 		}
   2717 
   2718 		if (query == NULL)
   2719 			goto error;
   2720 
   2721 		ret = wpas_p2p_service_del_bonjour(wpa_s, query);
   2722 		if (ret != 0)
   2723 			goto error;
   2724 	} else
   2725 		goto error;
   2726 
   2727 	wpabuf_free(query);
   2728 	os_free(service);
   2729 	return reply;
   2730 error_clear:
   2731 	wpa_dbus_dict_entry_clear(&entry);
   2732 error:
   2733 	wpabuf_free(query);
   2734 	os_free(service);
   2735 	return wpas_dbus_error_invalid_args(message, NULL);
   2736 }
   2737 
   2738 
   2739 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
   2740 						  struct wpa_supplicant *wpa_s)
   2741 {
   2742 	wpas_p2p_service_flush(wpa_s);
   2743 	return NULL;
   2744 }
   2745 
   2746 
   2747 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
   2748 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2749 {
   2750 	DBusMessageIter iter_dict;
   2751 	DBusMessage *reply = NULL;
   2752 	DBusMessageIter iter;
   2753 	struct wpa_dbus_dict_entry entry;
   2754 	int upnp = 0;
   2755 	char *service = NULL;
   2756 	char *peer_object_path = NULL;
   2757 	struct wpabuf *tlv = NULL;
   2758 	u8 version = 0;
   2759 	u64 ref = 0;
   2760 	u8 addr_buf[ETH_ALEN], *addr;
   2761 
   2762 	dbus_message_iter_init(message, &iter);
   2763 
   2764 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
   2765 		goto error;
   2766 
   2767 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2768 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2769 			goto error;
   2770 		if (os_strcmp(entry.key, "peer_object") == 0 &&
   2771 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
   2772 			peer_object_path = os_strdup(entry.str_value);
   2773 		} else if (os_strcmp(entry.key, "service_type") == 0 &&
   2774 			   entry.type == DBUS_TYPE_STRING) {
   2775 			if (os_strcmp(entry.str_value, "upnp") == 0)
   2776 				upnp = 1;
   2777 			else
   2778 				goto error_clear;
   2779 		} else if (os_strcmp(entry.key, "version") == 0 &&
   2780 			   entry.type == DBUS_TYPE_INT32) {
   2781 			version = entry.uint32_value;
   2782 		} else if (os_strcmp(entry.key, "service") == 0 &&
   2783 			   entry.type == DBUS_TYPE_STRING) {
   2784 			service = os_strdup(entry.str_value);
   2785 		} else if (os_strcmp(entry.key, "tlv") == 0) {
   2786 			if (entry.type != DBUS_TYPE_ARRAY ||
   2787 			    entry.array_type != DBUS_TYPE_BYTE)
   2788 				goto error_clear;
   2789 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
   2790 						entry.array_len);
   2791 		} else
   2792 			goto error_clear;
   2793 
   2794 		wpa_dbus_dict_entry_clear(&entry);
   2795 	}
   2796 
   2797 	if (!peer_object_path) {
   2798 		addr = NULL;
   2799 	} else {
   2800 		if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
   2801 		    !p2p_peer_known(wpa_s->global->p2p, addr_buf))
   2802 			goto error;
   2803 
   2804 		addr = addr_buf;
   2805 	}
   2806 
   2807 	if (upnp == 1) {
   2808 		if (version <= 0 || service == NULL)
   2809 			goto error;
   2810 
   2811 		ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
   2812 	} else {
   2813 		if (tlv == NULL)
   2814 			goto error;
   2815 		ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
   2816 		wpabuf_free(tlv);
   2817 	}
   2818 
   2819 	if (ref != 0) {
   2820 		reply = dbus_message_new_method_return(message);
   2821 		dbus_message_append_args(reply, DBUS_TYPE_UINT64,
   2822 					 &ref, DBUS_TYPE_INVALID);
   2823 	} else {
   2824 		reply = wpas_dbus_error_unknown_error(
   2825 			message, "Unable to send SD request");
   2826 	}
   2827 out:
   2828 	os_free(service);
   2829 	os_free(peer_object_path);
   2830 	return reply;
   2831 error_clear:
   2832 	wpa_dbus_dict_entry_clear(&entry);
   2833 error:
   2834 	if (tlv)
   2835 		wpabuf_free(tlv);
   2836 	reply = wpas_dbus_error_invalid_args(message, NULL);
   2837 	goto out;
   2838 }
   2839 
   2840 
   2841 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
   2842 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2843 {
   2844 	DBusMessageIter iter_dict;
   2845 	DBusMessage *reply = NULL;
   2846 	DBusMessageIter iter;
   2847 	struct wpa_dbus_dict_entry entry;
   2848 	char *peer_object_path = NULL;
   2849 	struct wpabuf *tlv = NULL;
   2850 	int freq = 0;
   2851 	int dlg_tok = 0;
   2852 	u8 addr[ETH_ALEN];
   2853 
   2854 	dbus_message_iter_init(message, &iter);
   2855 
   2856 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
   2857 		goto error;
   2858 
   2859 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
   2860 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
   2861 			goto error;
   2862 
   2863 		if (os_strcmp(entry.key, "peer_object") == 0 &&
   2864 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
   2865 			peer_object_path = os_strdup(entry.str_value);
   2866 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
   2867 			   entry.type == DBUS_TYPE_INT32) {
   2868 			freq = entry.uint32_value;
   2869 		} else if (os_strcmp(entry.key, "dialog_token") == 0 &&
   2870 			   (entry.type == DBUS_TYPE_UINT32 ||
   2871 			    entry.type == DBUS_TYPE_INT32)) {
   2872 			dlg_tok = entry.uint32_value;
   2873 		} else if (os_strcmp(entry.key, "tlvs") == 0) {
   2874 			if (entry.type != DBUS_TYPE_ARRAY ||
   2875 			    entry.array_type != DBUS_TYPE_BYTE)
   2876 				goto error_clear;
   2877 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
   2878 						entry.array_len);
   2879 		} else
   2880 			goto error_clear;
   2881 
   2882 		wpa_dbus_dict_entry_clear(&entry);
   2883 	}
   2884 	if (parse_peer_object_path(peer_object_path, addr) < 0 ||
   2885 	    !p2p_peer_known(wpa_s->global->p2p, addr) ||
   2886 	    tlv == NULL)
   2887 		goto error;
   2888 
   2889 	wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
   2890 	wpabuf_free(tlv);
   2891 out:
   2892 	os_free(peer_object_path);
   2893 	return reply;
   2894 error_clear:
   2895 	wpa_dbus_dict_entry_clear(&entry);
   2896 error:
   2897 	reply = wpas_dbus_error_invalid_args(message, NULL);
   2898 	goto out;
   2899 }
   2900 
   2901 
   2902 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
   2903 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2904 {
   2905 	DBusMessageIter iter;
   2906 	u64 req = 0;
   2907 
   2908 	dbus_message_iter_init(message, &iter);
   2909 	dbus_message_iter_get_basic(&iter, &req);
   2910 
   2911 	if (req == 0)
   2912 		goto error;
   2913 
   2914 	if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
   2915 		goto error;
   2916 
   2917 	return NULL;
   2918 error:
   2919 	return wpas_dbus_error_invalid_args(message, NULL);
   2920 }
   2921 
   2922 
   2923 DBusMessage * wpas_dbus_handler_p2p_service_update(
   2924 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2925 {
   2926 	wpas_p2p_sd_service_update(wpa_s);
   2927 	return NULL;
   2928 }
   2929 
   2930 
   2931 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
   2932 	DBusMessage *message, struct wpa_supplicant *wpa_s)
   2933 {
   2934 	DBusMessageIter iter;
   2935 	int ext = 0;
   2936 
   2937 	dbus_message_iter_init(message, &iter);
   2938 	dbus_message_iter_get_basic(&iter, &ext);
   2939 
   2940 	wpa_s->p2p_sd_over_ctrl_iface = ext;
   2941 
   2942 	return NULL;
   2943 
   2944 }
   2945 
   2946 
   2947 #ifdef CONFIG_WIFI_DISPLAY
   2948 
   2949 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
   2950 	const struct wpa_dbus_property_desc *property_desc,
   2951 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2952 {
   2953 	struct wpa_global *global = user_data;
   2954 	struct wpabuf *ie;
   2955 	dbus_bool_t ret;
   2956 
   2957 	ie = wifi_display_get_wfd_ie(global);
   2958 	if (ie == NULL)
   2959 		return wpas_dbus_simple_array_property_getter(iter,
   2960 							      DBUS_TYPE_BYTE,
   2961 							      NULL, 0, error);
   2962 
   2963 	ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
   2964 						     wpabuf_head(ie),
   2965 						     wpabuf_len(ie), error);
   2966 	wpabuf_free(ie);
   2967 
   2968 	return ret;
   2969 }
   2970 
   2971 
   2972 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
   2973 	const struct wpa_dbus_property_desc *property_desc,
   2974 	DBusMessageIter *iter, DBusError *error, void *user_data)
   2975 {
   2976 	struct wpa_global *global = user_data;
   2977 	DBusMessageIter variant, array;
   2978 	struct wpabuf *ie = NULL;
   2979 	const u8 *data;
   2980 	int len;
   2981 
   2982 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
   2983 		goto err;
   2984 
   2985 	dbus_message_iter_recurse(iter, &variant);
   2986 	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
   2987 		goto err;
   2988 
   2989 	dbus_message_iter_recurse(&variant, &array);
   2990 	dbus_message_iter_get_fixed_array(&array, &data, &len);
   2991 	if (len == 0) {
   2992 		wifi_display_enable(global, 0);
   2993 		wifi_display_deinit(global);
   2994 
   2995 		return TRUE;
   2996 	}
   2997 
   2998 	ie = wpabuf_alloc(len);
   2999 	if (ie == NULL)
   3000 		goto err;
   3001 
   3002 	wpabuf_put_data(ie, data, len);
   3003 	if (wifi_display_subelem_set_from_ies(global, ie) != 0)
   3004 		goto err;
   3005 
   3006 	if (global->wifi_display == 0)
   3007 		wifi_display_enable(global, 1);
   3008 
   3009 	wpabuf_free(ie);
   3010 
   3011 	return TRUE;
   3012 err:
   3013 	wpabuf_free(ie);
   3014 
   3015 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
   3016 			     "invalid message format");
   3017 	return FALSE;
   3018 }
   3019 
   3020 #endif /* CONFIG_WIFI_DISPLAY */
   3021