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