xref: /freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c (revision 43a5ec4eb41567cc92586503212743d89686d78f)
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 
748 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
749 		return reply;
750 
751 	dbus_message_iter_init(message, &iter);
752 
753 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
754 		goto err;
755 
756 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
757 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
758 			goto err;
759 
760 		if (os_strcmp(entry.key, "peer") == 0 &&
761 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
762 			peer_object_path = os_strdup(entry.str_value);
763 			wpa_dbus_dict_entry_clear(&entry);
764 		} else if (os_strcmp(entry.key, "persistent_group_object") ==
765 			   0 &&
766 			   entry.type == DBUS_TYPE_OBJECT_PATH) {
767 			pg_object_path = os_strdup(entry.str_value);
768 			persistent = 1;
769 			wpa_dbus_dict_entry_clear(&entry);
770 		} else {
771 			wpa_dbus_dict_entry_clear(&entry);
772 			goto err;
773 		}
774 	}
775 
776 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0 ||
777 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
778 		goto err;
779 
780 	wpa_s = wpa_s->global->p2p_init_wpa_s;
781 
782 	if (persistent) {
783 		char *net_id_str;
784 		/*
785 		 * A group ID is defined meaning we want to re-invoke a
786 		 * persistent group
787 		 */
788 
789 		iface = wpas_dbus_new_decompose_object_path(
790 			pg_object_path,
791 			WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
792 			&net_id_str);
793 		if (iface == NULL || net_id_str == NULL ||
794 		    !wpa_s->parent->dbus_new_path ||
795 		    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
796 			reply = wpas_dbus_error_invalid_args(message,
797 							     pg_object_path);
798 			goto out;
799 		}
800 
801 		group_id = strtoul(net_id_str, NULL, 10);
802 		if (errno == EINVAL) {
803 			reply = wpas_dbus_error_invalid_args(
804 				message, pg_object_path);
805 			goto out;
806 		}
807 
808 		/* Get the SSID structure from the persistent group id */
809 		ssid = wpa_config_get_network(wpa_s->conf, group_id);
810 		if (ssid == NULL || ssid->disabled != 2)
811 			goto err;
812 
813 		if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
814 				    0, 0, 0, false) < 0) {
815 			reply = wpas_dbus_error_unknown_error(
816 				message,
817 				"Failed to reinvoke a persistent group");
818 			goto out;
819 		}
820 	} else {
821 		/*
822 		 * No group ID means propose to a peer to join my active group
823 		 */
824 		if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
825 					  peer_addr, NULL, false)) {
826 			reply = wpas_dbus_error_unknown_error(
827 				message, "Failed to join to an active group");
828 			goto out;
829 		}
830 	}
831 
832 out:
833 	os_free(iface);
834 	os_free(pg_object_path);
835 	os_free(peer_object_path);
836 	return reply;
837 
838 err:
839 	reply = wpas_dbus_error_invalid_args(message, NULL);
840 	goto out;
841 }
842 
843 
844 DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
845 						  struct wpa_supplicant *wpa_s)
846 {
847 	DBusMessageIter iter;
848 	char *peer_object_path = NULL;
849 	char *config_method = NULL;
850 	u8 peer_addr[ETH_ALEN];
851 
852 	dbus_message_iter_init(message, &iter);
853 	dbus_message_iter_get_basic(&iter, &peer_object_path);
854 
855 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
856 		return wpas_dbus_error_invalid_args(message, NULL);
857 
858 	dbus_message_iter_next(&iter);
859 	dbus_message_iter_get_basic(&iter, &config_method);
860 
861 	/*
862 	 * Validation checks on config_method are being duplicated here
863 	 * to be able to return invalid args reply since the error code
864 	 * from p2p module are not granular enough (yet).
865 	 */
866 	if (os_strcmp(config_method, "display") &&
867 	    os_strcmp(config_method, "keypad") &&
868 	    os_strcmp(config_method, "pbc") &&
869 	    os_strcmp(config_method, "pushbutton"))
870 		return wpas_dbus_error_invalid_args(message, NULL);
871 
872 	wpa_s = wpa_s->global->p2p_init_wpa_s;
873 	if (!wpa_s)
874 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
875 
876 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
877 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
878 		return wpas_dbus_error_unknown_error(message,
879 				"Failed to send provision discovery request");
880 
881 	return NULL;
882 }
883 
884 
885 /*
886  * P2P Device property accessor methods.
887  */
888 
889 dbus_bool_t wpas_dbus_getter_p2p_device_config(
890 	const struct wpa_dbus_property_desc *property_desc,
891 	DBusMessageIter *iter, DBusError *error, void *user_data)
892 {
893 	struct wpa_supplicant *wpa_s = user_data;
894 	DBusMessageIter variant_iter, dict_iter;
895 	DBusMessageIter iter_secdev_dict_entry, iter_secdev_dict_val,
896 		iter_secdev_dict_array;
897 	const char *dev_name;
898 	int num_vendor_extensions = 0;
899 	int i;
900 	const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
901 
902 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
903 		return FALSE;
904 
905 	wpa_s = wpa_s->global->p2p_init_wpa_s;
906 
907 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
908 					      "a{sv}", &variant_iter) ||
909 	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
910 		goto err_no_mem;
911 
912 	/* DeviceName */
913 	dev_name = wpa_s->conf->device_name;
914 	if (dev_name &&
915 	    !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
916 		goto err_no_mem;
917 
918 	/* Primary device type */
919 	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
920 					     (char *) wpa_s->conf->device_type,
921 					     WPS_DEV_TYPE_LEN))
922 		goto err_no_mem;
923 
924 	/* Secondary device types */
925 	if (wpa_s->conf->num_sec_device_types) {
926 		if (!wpa_dbus_dict_begin_array(&dict_iter,
927 					       "SecondaryDeviceTypes",
928 					       DBUS_TYPE_ARRAY_AS_STRING
929 					       DBUS_TYPE_BYTE_AS_STRING,
930 					       &iter_secdev_dict_entry,
931 					       &iter_secdev_dict_val,
932 					       &iter_secdev_dict_array))
933 			goto err_no_mem;
934 
935 		for (i = 0; i < wpa_s->conf->num_sec_device_types; i++)
936 			wpa_dbus_dict_bin_array_add_element(
937 				&iter_secdev_dict_array,
938 				wpa_s->conf->sec_device_type[i],
939 				WPS_DEV_TYPE_LEN);
940 
941 		if (!wpa_dbus_dict_end_array(&dict_iter,
942 					     &iter_secdev_dict_entry,
943 					     &iter_secdev_dict_val,
944 					     &iter_secdev_dict_array))
945 			goto err_no_mem;
946 	}
947 
948 	/* GO IP address */
949 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_go) &&
950 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
951 					     (char *) wpa_s->conf->ip_addr_go,
952 					     4))
953 		goto err_no_mem;
954 
955 	/* IP address mask */
956 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_mask) &&
957 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
958 					     (char *) wpa_s->conf->ip_addr_mask,
959 					     4))
960 		goto err_no_mem;
961 
962 	/* IP address start */
963 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_start) &&
964 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrStart",
965 					     (char *)
966 					     wpa_s->conf->ip_addr_start,
967 					     4))
968 		goto err_no_mem;
969 
970 	/* IP address end */
971 	if (WPA_GET_BE32(wpa_s->conf->ip_addr_end) &&
972 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrEnd",
973 					     (char *) wpa_s->conf->ip_addr_end,
974 					     4))
975 		goto err_no_mem;
976 
977 	/* Vendor Extensions */
978 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
979 		if (wpa_s->conf->wps_vendor_ext[i] == NULL)
980 			continue;
981 		vendor_ext[num_vendor_extensions++] =
982 			wpa_s->conf->wps_vendor_ext[i];
983 	}
984 
985 	if ((num_vendor_extensions &&
986 	     !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
987 						"VendorExtension",
988 						vendor_ext,
989 						num_vendor_extensions)) ||
990 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
991 					 wpa_s->conf->p2p_go_intent) ||
992 	    !wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
993 				       wpa_s->conf->persistent_reconnect) ||
994 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
995 					 wpa_s->conf->p2p_listen_reg_class) ||
996 	    !wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
997 					 wpa_s->conf->p2p_listen_channel) ||
998 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
999 					 wpa_s->conf->p2p_oper_reg_class) ||
1000 	    !wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
1001 					 wpa_s->conf->p2p_oper_channel) ||
1002 	    (wpa_s->conf->p2p_ssid_postfix &&
1003 	     !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
1004 					  wpa_s->conf->p2p_ssid_postfix)) ||
1005 	    !wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
1006 				       wpa_s->conf->p2p_intra_bss) ||
1007 	    !wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
1008 					 wpa_s->conf->p2p_group_idle) ||
1009 	    !wpa_dbus_dict_append_uint32(&dict_iter, "disassoc_low_ack",
1010 					 wpa_s->conf->disassoc_low_ack) ||
1011 	    !wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
1012 				       wpa_s->conf->p2p_no_group_iface) ||
1013 	    !wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
1014 					 wpa_s->conf->p2p_search_delay) ||
1015 	    !wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
1016 	    !dbus_message_iter_close_container(iter, &variant_iter))
1017 		goto err_no_mem;
1018 
1019 	return TRUE;
1020 
1021 err_no_mem:
1022 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1023 	return FALSE;
1024 }
1025 
1026 
1027 dbus_bool_t wpas_dbus_setter_p2p_device_config(
1028 	const struct wpa_dbus_property_desc *property_desc,
1029 	DBusMessageIter *iter, DBusError *error, void *user_data)
1030 {
1031 	struct wpa_supplicant *wpa_s = user_data;
1032 	DBusMessageIter variant_iter, iter_dict;
1033 	struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
1034 	unsigned int i;
1035 
1036 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
1037 		return FALSE;
1038 
1039 	wpa_s = wpa_s->global->p2p_init_wpa_s;
1040 
1041 	dbus_message_iter_recurse(iter, &variant_iter);
1042 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
1043 		return FALSE;
1044 
1045 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
1046 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
1047 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1048 					     "invalid message format");
1049 			return FALSE;
1050 		}
1051 
1052 		if (os_strcmp(entry.key, "DeviceName") == 0) {
1053 			char *devname;
1054 
1055 			if (entry.type != DBUS_TYPE_STRING ||
1056 			    os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
1057 				goto error;
1058 
1059 			devname = os_strdup(entry.str_value);
1060 			if (devname == NULL)
1061 				goto err_no_mem_clear;
1062 
1063 			os_free(wpa_s->conf->device_name);
1064 			wpa_s->conf->device_name = devname;
1065 
1066 			wpa_s->conf->changed_parameters |=
1067 				CFG_CHANGED_DEVICE_NAME;
1068 		} else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
1069 			if (entry.type != DBUS_TYPE_ARRAY ||
1070 			    entry.array_type != DBUS_TYPE_BYTE ||
1071 			    entry.array_len != WPS_DEV_TYPE_LEN)
1072 				goto error;
1073 
1074 			os_memcpy(wpa_s->conf->device_type,
1075 				  entry.bytearray_value,
1076 				  WPS_DEV_TYPE_LEN);
1077 			wpa_s->conf->changed_parameters |=
1078 				CFG_CHANGED_DEVICE_TYPE;
1079 		} else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
1080 			if (entry.type != DBUS_TYPE_ARRAY ||
1081 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1082 			    entry.array_len > MAX_SEC_DEVICE_TYPES)
1083 				goto error;
1084 
1085 			for (i = 0; i < entry.array_len; i++)
1086 				if (wpabuf_len(entry.binarray_value[i]) !=
1087 				    WPS_DEV_TYPE_LEN)
1088 					goto err_no_mem_clear;
1089 			for (i = 0; i < entry.array_len; i++)
1090 				os_memcpy(wpa_s->conf->sec_device_type[i],
1091 					  wpabuf_head(entry.binarray_value[i]),
1092 					  WPS_DEV_TYPE_LEN);
1093 			wpa_s->conf->num_sec_device_types = entry.array_len;
1094 			wpa_s->conf->changed_parameters |=
1095 					CFG_CHANGED_SEC_DEVICE_TYPE;
1096 		} else if (os_strcmp(entry.key, "VendorExtension") == 0) {
1097 			if (entry.type != DBUS_TYPE_ARRAY ||
1098 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
1099 			    (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
1100 				goto error;
1101 
1102 			wpa_s->conf->changed_parameters |=
1103 				CFG_CHANGED_VENDOR_EXTENSION;
1104 
1105 			for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1106 				wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
1107 				if (i < entry.array_len) {
1108 					wpa_s->conf->wps_vendor_ext[i] =
1109 						entry.binarray_value[i];
1110 					entry.binarray_value[i] = NULL;
1111 				} else
1112 					wpa_s->conf->wps_vendor_ext[i] = NULL;
1113 			}
1114 		} else if (os_strcmp(entry.key, "GOIntent") == 0 &&
1115 			   entry.type == DBUS_TYPE_UINT32 &&
1116 			   (entry.uint32_value <= 15))
1117 			wpa_s->conf->p2p_go_intent = entry.uint32_value;
1118 		else if (os_strcmp(entry.key, "PersistentReconnect") == 0 &&
1119 			 entry.type == DBUS_TYPE_BOOLEAN)
1120 			wpa_s->conf->persistent_reconnect = entry.bool_value;
1121 		else if (os_strcmp(entry.key, "ListenRegClass") == 0 &&
1122 			 entry.type == DBUS_TYPE_UINT32) {
1123 			wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
1124 			wpa_s->conf->changed_parameters |=
1125 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
1126 		} else if (os_strcmp(entry.key, "ListenChannel") == 0 &&
1127 			   entry.type == DBUS_TYPE_UINT32) {
1128 			wpa_s->conf->p2p_listen_channel = entry.uint32_value;
1129 			wpa_s->conf->changed_parameters |=
1130 				CFG_CHANGED_P2P_LISTEN_CHANNEL;
1131 		} else if (os_strcmp(entry.key, "OperRegClass") == 0 &&
1132 			   entry.type == DBUS_TYPE_UINT32) {
1133 			wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
1134 			wpa_s->conf->changed_parameters |=
1135 				CFG_CHANGED_P2P_OPER_CHANNEL;
1136 		} else if (os_strcmp(entry.key, "OperChannel") == 0 &&
1137 			   entry.type == DBUS_TYPE_UINT32) {
1138 			wpa_s->conf->p2p_oper_channel = entry.uint32_value;
1139 			wpa_s->conf->changed_parameters |=
1140 				CFG_CHANGED_P2P_OPER_CHANNEL;
1141 		} else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
1142 			char *postfix;
1143 
1144 			if (entry.type != DBUS_TYPE_STRING)
1145 				goto error;
1146 
1147 			postfix = os_strdup(entry.str_value);
1148 			if (!postfix)
1149 				goto err_no_mem_clear;
1150 
1151 			os_free(wpa_s->conf->p2p_ssid_postfix);
1152 			wpa_s->conf->p2p_ssid_postfix = postfix;
1153 
1154 			wpa_s->conf->changed_parameters |=
1155 					CFG_CHANGED_P2P_SSID_POSTFIX;
1156 		} else if (os_strcmp(entry.key, "IntraBss") == 0 &&
1157 			   entry.type == DBUS_TYPE_BOOLEAN) {
1158 			wpa_s->conf->p2p_intra_bss = entry.bool_value;
1159 			wpa_s->conf->changed_parameters |=
1160 				CFG_CHANGED_P2P_INTRA_BSS;
1161 		} else if (os_strcmp(entry.key, "IpAddrGo") == 0) {
1162 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1163 				goto error;
1164 			os_memcpy(wpa_s->conf->ip_addr_go,
1165 				  entry.bytearray_value, 4);
1166 		} else if (os_strcmp(entry.key, "IpAddrMask") == 0) {
1167 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1168 				goto error;
1169 			os_memcpy(wpa_s->conf->ip_addr_mask,
1170 				  entry.bytearray_value, 4);
1171 		} else if (os_strcmp(entry.key, "IpAddrStart") == 0) {
1172 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1173 				goto error;
1174 			os_memcpy(wpa_s->conf->ip_addr_start,
1175 				  entry.bytearray_value, 4);
1176 		} else if (os_strcmp(entry.key, "IpAddrEnd") == 0) {
1177 			if (!wpas_dbus_validate_dbus_ipaddr(entry))
1178 				goto error;
1179 			os_memcpy(wpa_s->conf->ip_addr_end,
1180 				  entry.bytearray_value, 4);
1181 		} else if (os_strcmp(entry.key, "GroupIdle") == 0 &&
1182 			   entry.type == DBUS_TYPE_UINT32)
1183 			wpa_s->conf->p2p_group_idle = entry.uint32_value;
1184 		else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
1185 			 entry.type == DBUS_TYPE_UINT32)
1186 			wpa_s->conf->disassoc_low_ack = entry.uint32_value;
1187 		else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
1188 			 entry.type == DBUS_TYPE_BOOLEAN)
1189 			wpa_s->conf->p2p_no_group_iface = entry.bool_value;
1190 		else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
1191 			 entry.type == DBUS_TYPE_UINT32)
1192 			wpa_s->conf->p2p_search_delay = entry.uint32_value;
1193 		else
1194 			goto error;
1195 
1196 		wpa_dbus_dict_entry_clear(&entry);
1197 	}
1198 
1199 	if (wpa_s->conf->changed_parameters) {
1200 		/* Some changed parameters requires to update config*/
1201 		wpa_supplicant_update_config(wpa_s);
1202 	}
1203 
1204 	return TRUE;
1205 
1206  error:
1207 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
1208 			     "invalid message format");
1209 	wpa_dbus_dict_entry_clear(&entry);
1210 	return FALSE;
1211 
1212  err_no_mem_clear:
1213 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1214 	wpa_dbus_dict_entry_clear(&entry);
1215 	return FALSE;
1216 }
1217 
1218 
1219 dbus_bool_t wpas_dbus_getter_p2p_peers(
1220 	const struct wpa_dbus_property_desc *property_desc,
1221 	DBusMessageIter *iter, DBusError *error, void *user_data)
1222 {
1223 	struct wpa_supplicant *wpa_s = user_data;
1224 	struct p2p_data *p2p = wpa_s->global->p2p;
1225 	int next = 0, i = 0;
1226 	int num = 0, out_of_mem = 0;
1227 	const u8 *addr;
1228 	const struct p2p_peer_info *peer_info = NULL;
1229 	dbus_bool_t success = FALSE;
1230 
1231 	struct dl_list peer_objpath_list;
1232 	struct peer_objpath_node {
1233 		struct dl_list list;
1234 		char path[WPAS_DBUS_OBJECT_PATH_MAX];
1235 	} *node, *tmp;
1236 
1237 	char **peer_obj_paths = NULL;
1238 
1239 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error) ||
1240 	    !wpa_s->parent->parent->dbus_new_path)
1241 		return FALSE;
1242 
1243 	dl_list_init(&peer_objpath_list);
1244 
1245 	/* Get the first peer info */
1246 	peer_info = p2p_get_peer_found(p2p, NULL, next);
1247 
1248 	/* Get next and accumulate them */
1249 	next = 1;
1250 	while (peer_info != NULL) {
1251 		node = os_zalloc(sizeof(struct peer_objpath_node));
1252 		if (!node) {
1253 			out_of_mem = 1;
1254 			goto error;
1255 		}
1256 
1257 		addr = peer_info->p2p_device_addr;
1258 		os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
1259 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
1260 			    "/" COMPACT_MACSTR,
1261 			    wpa_s->parent->parent->dbus_new_path,
1262 			    MAC2STR(addr));
1263 		dl_list_add_tail(&peer_objpath_list, &node->list);
1264 		num++;
1265 
1266 		peer_info = p2p_get_peer_found(p2p, addr, next);
1267 	}
1268 
1269 	/*
1270 	 * Now construct the peer object paths in a form suitable for
1271 	 * array_property_getter helper below.
1272 	 */
1273 	peer_obj_paths = os_calloc(num, sizeof(char *));
1274 
1275 	if (!peer_obj_paths) {
1276 		out_of_mem = 1;
1277 		goto error;
1278 	}
1279 
1280 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1281 			      struct peer_objpath_node, list)
1282 		peer_obj_paths[i++] = node->path;
1283 
1284 	success = wpas_dbus_simple_array_property_getter(iter,
1285 							 DBUS_TYPE_OBJECT_PATH,
1286 							 peer_obj_paths, num,
1287 							 error);
1288 
1289 error:
1290 	if (peer_obj_paths)
1291 		os_free(peer_obj_paths);
1292 
1293 	dl_list_for_each_safe(node, tmp, &peer_objpath_list,
1294 			      struct peer_objpath_node, list) {
1295 		dl_list_del(&node->list);
1296 		os_free(node);
1297 	}
1298 	if (out_of_mem)
1299 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1300 
1301 	return success;
1302 }
1303 
1304 
1305 enum wpas_p2p_role {
1306 	WPAS_P2P_ROLE_DEVICE,
1307 	WPAS_P2P_ROLE_GO,
1308 	WPAS_P2P_ROLE_CLIENT,
1309 };
1310 
1311 static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
1312 {
1313 	struct wpa_ssid *ssid = wpa_s->current_ssid;
1314 
1315 	if (!ssid)
1316 		return WPAS_P2P_ROLE_DEVICE;
1317 	if (wpa_s->wpa_state != WPA_COMPLETED)
1318 		return WPAS_P2P_ROLE_DEVICE;
1319 
1320 	switch (ssid->mode) {
1321 	case WPAS_MODE_P2P_GO:
1322 	case WPAS_MODE_P2P_GROUP_FORMATION:
1323 		return WPAS_P2P_ROLE_GO;
1324 	case WPAS_MODE_INFRA:
1325 		if (ssid->p2p_group)
1326 			return WPAS_P2P_ROLE_CLIENT;
1327 		return WPAS_P2P_ROLE_DEVICE;
1328 	default:
1329 		return WPAS_P2P_ROLE_DEVICE;
1330 	}
1331 }
1332 
1333 
1334 dbus_bool_t wpas_dbus_getter_p2p_role(
1335 	const struct wpa_dbus_property_desc *property_desc,
1336 	DBusMessageIter *iter, DBusError *error, void *user_data)
1337 {
1338 	struct wpa_supplicant *wpa_s = user_data;
1339 	char *str;
1340 
1341 	switch (wpas_get_p2p_role(wpa_s)) {
1342 	case WPAS_P2P_ROLE_GO:
1343 		str = "GO";
1344 		break;
1345 	case WPAS_P2P_ROLE_CLIENT:
1346 		str = "client";
1347 		break;
1348 	default:
1349 		str = "device";
1350 		break;
1351 	}
1352 
1353 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
1354 						error);
1355 }
1356 
1357 
1358 dbus_bool_t wpas_dbus_getter_p2p_group(
1359 	const struct wpa_dbus_property_desc *property_desc,
1360 	DBusMessageIter *iter, DBusError *error, void *user_data)
1361 {
1362 	struct wpa_supplicant *wpa_s = user_data;
1363 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
1364 	char *dbus_groupobj_path = path_buf;
1365 
1366 	if (wpa_s->dbus_groupobj_path == NULL)
1367 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1368 			    "/");
1369 	else
1370 		os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1371 			    "%s", wpa_s->dbus_groupobj_path);
1372 
1373 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1374 						&dbus_groupobj_path, error);
1375 }
1376 
1377 
1378 dbus_bool_t wpas_dbus_getter_p2p_peergo(
1379 	const struct wpa_dbus_property_desc *property_desc,
1380 	DBusMessageIter *iter, DBusError *error, void *user_data)
1381 {
1382 	struct wpa_supplicant *wpa_s = user_data;
1383 	char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1384 
1385 	if (!wpa_s->parent->parent->dbus_new_path)
1386 		return FALSE;
1387 
1388 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
1389 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
1390 	else
1391 		os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1392 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1393 			    COMPACT_MACSTR,
1394 			    wpa_s->parent->parent->dbus_new_path,
1395 			    MAC2STR(wpa_s->go_dev_addr));
1396 
1397 	path = go_peer_obj_path;
1398 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
1399 						&path, error);
1400 }
1401 
1402 
1403 /*
1404  * Peer object properties accessor methods
1405  */
1406 
1407 dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
1408 	const struct wpa_dbus_property_desc *property_desc,
1409 	DBusMessageIter *iter, DBusError *error, void *user_data)
1410 {
1411 	struct peer_handler_args *peer_args = user_data;
1412 	const struct p2p_peer_info *info;
1413 	char *tmp;
1414 
1415 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1416 		return FALSE;
1417 
1418 	/* get the peer info */
1419 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1420 				  peer_args->p2p_device_addr, 0);
1421 	if (info == NULL) {
1422 		dbus_set_error(error, DBUS_ERROR_FAILED,
1423 			       "failed to find peer");
1424 		return FALSE;
1425 	}
1426 
1427 	tmp = os_strdup(info->device_name);
1428 	if (!tmp) {
1429 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1430 		return FALSE;
1431 	}
1432 
1433 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1434 					      error)) {
1435 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1436 		os_free(tmp);
1437 		return FALSE;
1438 	}
1439 
1440 	os_free(tmp);
1441 	return TRUE;
1442 }
1443 
1444 
1445 dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
1446 	const struct wpa_dbus_property_desc *property_desc,
1447 	DBusMessageIter *iter, DBusError *error, void *user_data)
1448 {
1449 	struct peer_handler_args *peer_args = user_data;
1450 	const struct p2p_peer_info *info;
1451 	char *tmp;
1452 
1453 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1454 		return FALSE;
1455 
1456 	/* get the peer info */
1457 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1458 				  peer_args->p2p_device_addr, 0);
1459 	if (info == NULL) {
1460 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1461 		return FALSE;
1462 	}
1463 
1464 	tmp = os_strdup(info->manufacturer);
1465 	if (!tmp) {
1466 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1467 		return FALSE;
1468 	}
1469 
1470 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1471 					      error)) {
1472 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1473 		os_free(tmp);
1474 		return FALSE;
1475 	}
1476 
1477 	os_free(tmp);
1478 	return TRUE;
1479 }
1480 
1481 
1482 dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
1483 	const struct wpa_dbus_property_desc *property_desc,
1484 	DBusMessageIter *iter, DBusError *error, void *user_data)
1485 {
1486 	struct peer_handler_args *peer_args = user_data;
1487 	const struct p2p_peer_info *info;
1488 	char *tmp;
1489 
1490 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1491 		return FALSE;
1492 
1493 	/* get the peer info */
1494 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1495 				  peer_args->p2p_device_addr, 0);
1496 	if (info == NULL) {
1497 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1498 		return FALSE;
1499 	}
1500 
1501 	tmp = os_strdup(info->model_name);
1502 	if (!tmp) {
1503 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1504 		return FALSE;
1505 	}
1506 
1507 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1508 					      error)) {
1509 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1510 		os_free(tmp);
1511 		return FALSE;
1512 	}
1513 
1514 	os_free(tmp);
1515 	return TRUE;
1516 }
1517 
1518 
1519 dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
1520 	const struct wpa_dbus_property_desc *property_desc,
1521 	DBusMessageIter *iter, DBusError *error, void *user_data)
1522 {
1523 	struct peer_handler_args *peer_args = user_data;
1524 	const struct p2p_peer_info *info;
1525 	char *tmp;
1526 
1527 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1528 		return FALSE;
1529 
1530 	/* get the peer info */
1531 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1532 				  peer_args->p2p_device_addr, 0);
1533 	if (info == NULL) {
1534 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1535 		return FALSE;
1536 	}
1537 
1538 	tmp = os_strdup(info->model_number);
1539 	if (!tmp) {
1540 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1541 		return FALSE;
1542 	}
1543 
1544 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1545 					      error)) {
1546 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1547 		os_free(tmp);
1548 		return FALSE;
1549 	}
1550 
1551 	os_free(tmp);
1552 	return TRUE;
1553 }
1554 
1555 
1556 dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
1557 	const struct wpa_dbus_property_desc *property_desc,
1558 	DBusMessageIter *iter, DBusError *error, void *user_data)
1559 {
1560 	struct peer_handler_args *peer_args = user_data;
1561 	const struct p2p_peer_info *info;
1562 	char *tmp;
1563 
1564 	if (!wpa_dbus_p2p_check_enabled(peer_args->wpa_s, NULL, NULL, error))
1565 		return FALSE;
1566 
1567 	/* get the peer info */
1568 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1569 				  peer_args->p2p_device_addr, 0);
1570 	if (info == NULL) {
1571 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1572 		return FALSE;
1573 	}
1574 
1575 	tmp = os_strdup(info->serial_number);
1576 	if (!tmp) {
1577 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1578 		return FALSE;
1579 	}
1580 
1581 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &tmp,
1582 					      error)) {
1583 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1584 		os_free(tmp);
1585 		return FALSE;
1586 	}
1587 
1588 	os_free(tmp);
1589 	return TRUE;
1590 }
1591 
1592 
1593 dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
1594 	const struct wpa_dbus_property_desc *property_desc,
1595 	DBusMessageIter *iter, DBusError *error, void *user_data)
1596 {
1597 	struct peer_handler_args *peer_args = user_data;
1598 	const struct p2p_peer_info *info;
1599 
1600 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1601 				  peer_args->p2p_device_addr, 0);
1602 	if (info == NULL) {
1603 		dbus_set_error(error, DBUS_ERROR_FAILED,
1604 			       "failed to find peer");
1605 		return FALSE;
1606 	}
1607 
1608 	if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
1609 						    (char *)
1610 						    info->pri_dev_type,
1611 						    WPS_DEV_TYPE_LEN, error)) {
1612 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1613 		return FALSE;
1614 	}
1615 
1616 	return TRUE;
1617 }
1618 
1619 
1620 dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
1621 	const struct wpa_dbus_property_desc *property_desc,
1622 	DBusMessageIter *iter, DBusError *error, void *user_data)
1623 {
1624 	struct peer_handler_args *peer_args = user_data;
1625 	const struct p2p_peer_info *info;
1626 
1627 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1628 				  peer_args->p2p_device_addr, 0);
1629 	if (info == NULL) {
1630 		dbus_set_error(error, DBUS_ERROR_FAILED,
1631 			       "failed to find peer");
1632 		return FALSE;
1633 	}
1634 
1635 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
1636 					      &info->config_methods, error)) {
1637 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1638 		return FALSE;
1639 	}
1640 
1641 	return TRUE;
1642 }
1643 
1644 
1645 dbus_bool_t wpas_dbus_getter_p2p_peer_level(
1646 	const struct wpa_dbus_property_desc *property_desc,
1647 	DBusMessageIter *iter, DBusError *error, void *user_data)
1648 {
1649 	struct peer_handler_args *peer_args = user_data;
1650 	const struct p2p_peer_info *info;
1651 
1652 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1653 				  peer_args->p2p_device_addr, 0);
1654 	if (info == NULL) {
1655 		dbus_set_error(error, DBUS_ERROR_FAILED,
1656 			       "failed to find peer");
1657 		return FALSE;
1658 	}
1659 
1660 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
1661 					      &info->level, error)) {
1662 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1663 		return FALSE;
1664 	}
1665 
1666 	return TRUE;
1667 }
1668 
1669 
1670 dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
1671 	const struct wpa_dbus_property_desc *property_desc,
1672 	DBusMessageIter *iter, DBusError *error, void *user_data)
1673 {
1674 	struct peer_handler_args *peer_args = user_data;
1675 	const struct p2p_peer_info *info;
1676 
1677 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1678 				  peer_args->p2p_device_addr, 0);
1679 	if (info == NULL) {
1680 		dbus_set_error(error, DBUS_ERROR_FAILED,
1681 			       "failed to find peer");
1682 		return FALSE;
1683 	}
1684 
1685 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1686 					      &info->dev_capab, error)) {
1687 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1688 		return FALSE;
1689 	}
1690 
1691 	return TRUE;
1692 }
1693 
1694 
1695 dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
1696 	const struct wpa_dbus_property_desc *property_desc,
1697 	DBusMessageIter *iter, DBusError *error, void *user_data)
1698 {
1699 	struct peer_handler_args *peer_args = user_data;
1700 	const struct p2p_peer_info *info;
1701 
1702 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1703 				  peer_args->p2p_device_addr, 0);
1704 	if (info == NULL) {
1705 		dbus_set_error(error, DBUS_ERROR_FAILED,
1706 			       "failed to find peer");
1707 		return FALSE;
1708 	}
1709 
1710 	if (!wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BYTE,
1711 					      &info->group_capab, error)) {
1712 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1713 		return FALSE;
1714 	}
1715 
1716 	return TRUE;
1717 }
1718 
1719 
1720 dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
1721 	const struct wpa_dbus_property_desc *property_desc,
1722 	DBusMessageIter *iter, DBusError *error, void *user_data)
1723 {
1724 	struct peer_handler_args *peer_args = user_data;
1725 	const struct p2p_peer_info *info;
1726 	DBusMessageIter variant_iter, array_iter;
1727 
1728 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1729 				  peer_args->p2p_device_addr, 0);
1730 	if (info == NULL) {
1731 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1732 		return FALSE;
1733 	}
1734 
1735 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
1736 					      DBUS_TYPE_ARRAY_AS_STRING
1737 					      DBUS_TYPE_ARRAY_AS_STRING
1738 					      DBUS_TYPE_BYTE_AS_STRING,
1739 					      &variant_iter) ||
1740 	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
1741 					      DBUS_TYPE_ARRAY_AS_STRING
1742 					      DBUS_TYPE_BYTE_AS_STRING,
1743 					      &array_iter)) {
1744 		dbus_set_error(error, DBUS_ERROR_FAILED,
1745 			       "%s: failed to construct message 1", __func__);
1746 		return FALSE;
1747 	}
1748 
1749 	if (info->wps_sec_dev_type_list_len) {
1750 		const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
1751 		int num_sec_device_types =
1752 			info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
1753 		int i;
1754 		DBusMessageIter inner_array_iter;
1755 
1756 		for (i = 0; i < num_sec_device_types; i++) {
1757 			if (!dbus_message_iter_open_container(
1758 				    &array_iter, DBUS_TYPE_ARRAY,
1759 				    DBUS_TYPE_BYTE_AS_STRING,
1760 				    &inner_array_iter) ||
1761 			    !dbus_message_iter_append_fixed_array(
1762 				    &inner_array_iter, DBUS_TYPE_BYTE,
1763 				    &sec_dev_type_list, WPS_DEV_TYPE_LEN) ||
1764 			    !dbus_message_iter_close_container(
1765 				    &array_iter, &inner_array_iter)) {
1766 				dbus_set_error(error, DBUS_ERROR_FAILED,
1767 					       "%s: failed to construct message 2 (%d)",
1768 					       __func__, i);
1769 				return FALSE;
1770 			}
1771 
1772 			sec_dev_type_list += WPS_DEV_TYPE_LEN;
1773 		}
1774 	}
1775 
1776 	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
1777 	    !dbus_message_iter_close_container(iter, &variant_iter)) {
1778 		dbus_set_error(error, DBUS_ERROR_FAILED,
1779 			       "%s: failed to construct message 3", __func__);
1780 		return FALSE;
1781 	}
1782 
1783 	return TRUE;
1784 }
1785 
1786 
1787 dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
1788 	const struct wpa_dbus_property_desc *property_desc,
1789 	DBusMessageIter *iter, DBusError *error, void *user_data)
1790 {
1791 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
1792 	unsigned int i, num = 0;
1793 	struct peer_handler_args *peer_args = user_data;
1794 	const struct p2p_peer_info *info;
1795 
1796 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1797 				  peer_args->p2p_device_addr, 0);
1798 	if (info == NULL) {
1799 		dbus_set_error(error, DBUS_ERROR_FAILED,
1800 			       "failed to find peer");
1801 		return FALSE;
1802 	}
1803 
1804 	/* Add WPS vendor extensions attribute */
1805 	os_memset(vendor_extension, 0, sizeof(vendor_extension));
1806 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
1807 		if (info->wps_vendor_ext[i] == NULL)
1808 			continue;
1809 		vendor_extension[num] = info->wps_vendor_ext[i];
1810 		num++;
1811 	}
1812 
1813 	if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
1814 							  vendor_extension,
1815 							  num, error))
1816 		return FALSE;
1817 
1818 	return TRUE;
1819 }
1820 
1821 
1822 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
1823 	const struct wpa_dbus_property_desc *property_desc,
1824 	DBusMessageIter *iter, DBusError *error, void *user_data)
1825 {
1826 	struct peer_handler_args *peer_args = user_data;
1827 	const struct p2p_peer_info *info;
1828 
1829 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1830 				  peer_args->p2p_device_addr, 0);
1831 	if (info == NULL) {
1832 		dbus_set_error(error, DBUS_ERROR_FAILED,
1833 			       "failed to find peer");
1834 		return FALSE;
1835 	}
1836 
1837 	if (info->wfd_subelems == NULL)
1838 		return wpas_dbus_simple_array_property_getter(iter,
1839 							      DBUS_TYPE_BYTE,
1840 							      NULL, 0, error);
1841 
1842 	return wpas_dbus_simple_array_property_getter(
1843 		iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
1844 		info->wfd_subelems->used, error);
1845 }
1846 
1847 
1848 dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
1849 	const struct wpa_dbus_property_desc *property_desc,
1850 	DBusMessageIter *iter, DBusError *error, void *user_data)
1851 {
1852 	struct peer_handler_args *peer_args = user_data;
1853 	const struct p2p_peer_info *info;
1854 
1855 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1856 				  peer_args->p2p_device_addr, 0);
1857 	if (info == NULL) {
1858 		dbus_set_error(error, DBUS_ERROR_FAILED,
1859 			       "failed to find peer");
1860 		return FALSE;
1861 	}
1862 
1863 	return wpas_dbus_simple_array_property_getter(
1864 		iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
1865 		ETH_ALEN, error);
1866 }
1867 
1868 
1869 struct peer_group_data {
1870 	struct wpa_supplicant *wpa_s;
1871 	const struct p2p_peer_info *info;
1872 	char **paths;
1873 	unsigned int nb_paths;
1874 	int error;
1875 };
1876 
1877 
1878 static int match_group_where_peer_is_client(struct p2p_group *group,
1879 					    void *user_data)
1880 {
1881 	struct peer_group_data *data = user_data;
1882 	const struct p2p_group_config *cfg;
1883 	struct wpa_supplicant *wpa_s_go;
1884 	char **paths;
1885 
1886 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1887 		return 1;
1888 
1889 	cfg = p2p_group_get_config(group);
1890 
1891 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1892 					 cfg->ssid_len);
1893 	if (wpa_s_go == NULL)
1894 		return 1;
1895 
1896 	paths = os_realloc_array(data->paths, data->nb_paths + 1,
1897 				 sizeof(char *));
1898 	if (paths == NULL)
1899 		goto out_of_memory;
1900 
1901 	data->paths = paths;
1902 	data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
1903 	data->nb_paths++;
1904 
1905 	return 1;
1906 
1907 out_of_memory:
1908 	data->error = ENOMEM;
1909 	return 0;
1910 }
1911 
1912 
1913 dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
1914 	const struct wpa_dbus_property_desc *property_desc,
1915 	DBusMessageIter *iter, DBusError *error, void *user_data)
1916 {
1917 	struct peer_handler_args *peer_args = user_data;
1918 	const struct p2p_peer_info *info;
1919 	struct peer_group_data data;
1920 	struct wpa_supplicant *wpa_s, *wpa_s_go;
1921 	dbus_bool_t success = FALSE;
1922 
1923 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1924 				  peer_args->p2p_device_addr, 0);
1925 	if (info == NULL) {
1926 		dbus_set_error(error, DBUS_ERROR_FAILED,
1927 			       "failed to find peer");
1928 		return FALSE;
1929 	}
1930 
1931 	os_memset(&data, 0, sizeof(data));
1932 
1933 	wpa_s = peer_args->wpa_s;
1934 	wpa_s = wpa_s->global->p2p_init_wpa_s;
1935 	if (!wpa_s)
1936 		return no_p2p_mgmt_interface(error);
1937 
1938 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
1939 	if (wpa_s_go) {
1940 		data.paths = os_calloc(1, sizeof(char *));
1941 		if (data.paths == NULL)
1942 			goto out_of_memory;
1943 		data.paths[0] = wpa_s_go->dbus_groupobj_path;
1944 		data.nb_paths = 1;
1945 	}
1946 
1947 	data.wpa_s = peer_args->wpa_s;
1948 	data.info = info;
1949 
1950 	p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
1951 			       match_group_where_peer_is_client, &data);
1952 	if (data.error)
1953 		goto out_of_memory;
1954 
1955 	if (data.paths == NULL) {
1956 		return wpas_dbus_simple_array_property_getter(
1957 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
1958 	}
1959 
1960 	success = wpas_dbus_simple_array_property_getter(iter,
1961 							 DBUS_TYPE_OBJECT_PATH,
1962 							 data.paths,
1963 							 data.nb_paths, error);
1964 	goto out;
1965 
1966 out_of_memory:
1967 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
1968 out:
1969 	os_free(data.paths);
1970 	return success;
1971 }
1972 
1973 dbus_bool_t wpas_dbus_getter_p2p_peer_vsie(
1974 	const struct wpa_dbus_property_desc *property_desc,
1975 	DBusMessageIter *iter, DBusError *error, void *user_data)
1976 {
1977 	struct peer_handler_args *peer_args = user_data;
1978 	const struct p2p_peer_info *info;
1979 
1980 	info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
1981 				  peer_args->p2p_device_addr, 0);
1982 	if (!info) {
1983 		dbus_set_error(error, DBUS_ERROR_FAILED, "failed to find peer");
1984 		return FALSE;
1985 	}
1986 
1987 	if (!info->vendor_elems)
1988 		return wpas_dbus_simple_array_property_getter(iter,
1989 							      DBUS_TYPE_BYTE,
1990 							      NULL, 0, error);
1991 
1992 	return wpas_dbus_simple_array_property_getter(
1993 		iter, DBUS_TYPE_BYTE, (char *) info->vendor_elems->buf,
1994 		info->vendor_elems->used, error);
1995 }
1996 
1997 
1998 /**
1999  * wpas_dbus_getter_persistent_groups - Get array of persistent group objects
2000  * @iter: Pointer to incoming dbus message iter
2001  * @error: Location to store error on failure
2002  * @user_data: Function specific data
2003  * Returns: TRUE on success, FALSE on failure
2004  *
2005  * Getter for "PersistentGroups" property.
2006  */
2007 dbus_bool_t wpas_dbus_getter_persistent_groups(
2008 	const struct wpa_dbus_property_desc *property_desc,
2009 	DBusMessageIter *iter, DBusError *error, void *user_data)
2010 {
2011 	struct wpa_supplicant *wpa_s = user_data;
2012 	struct wpa_ssid *ssid;
2013 	char **paths;
2014 	unsigned int i = 0, num = 0;
2015 	dbus_bool_t success = FALSE;
2016 
2017 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2018 	if (!wpa_s)
2019 		return no_p2p_mgmt_interface(error);
2020 
2021 	if (!wpa_s->parent->dbus_new_path)
2022 		return FALSE;
2023 
2024 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2025 		if (network_is_persistent_group(ssid))
2026 			num++;
2027 
2028 	paths = os_calloc(num, sizeof(char *));
2029 	if (!paths) {
2030 		dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2031 		return FALSE;
2032 	}
2033 
2034 	/* Loop through configured networks and append object path of each */
2035 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2036 		if (!network_is_persistent_group(ssid))
2037 			continue;
2038 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2039 		if (paths[i] == NULL) {
2040 			dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY,
2041 					     "no memory");
2042 			goto out;
2043 		}
2044 		/* Construct the object path for this network. */
2045 		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
2046 			    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2047 			    wpa_s->parent->dbus_new_path, ssid->id);
2048 	}
2049 
2050 	success = wpas_dbus_simple_array_property_getter(iter,
2051 							 DBUS_TYPE_OBJECT_PATH,
2052 							 paths, num, error);
2053 
2054 out:
2055 	while (i)
2056 		os_free(paths[--i]);
2057 	os_free(paths);
2058 	return success;
2059 }
2060 
2061 
2062 /**
2063  * wpas_dbus_getter_persistent_group_properties - Get options for a persistent
2064  *	group
2065  * @iter: Pointer to incoming dbus message iter
2066  * @error: Location to store error on failure
2067  * @user_data: Function specific data
2068  * Returns: TRUE on success, FALSE on failure
2069  *
2070  * Getter for "Properties" property of a persistent group.
2071  */
2072 dbus_bool_t wpas_dbus_getter_persistent_group_properties(
2073 	const struct wpa_dbus_property_desc *property_desc,
2074 	DBusMessageIter *iter, DBusError *error, void *user_data)
2075 {
2076 	struct network_handler_args *net = user_data;
2077 
2078 	/* Leveraging the fact that persistent group object is still
2079 	 * represented in same manner as network within.
2080 	 */
2081 	return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
2082 }
2083 
2084 
2085 /**
2086  * wpas_dbus_setter_persistent_group_properties - Set options for a persistent
2087  *	group
2088  * @iter: Pointer to incoming dbus message iter
2089  * @error: Location to store error on failure
2090  * @user_data: Function specific data
2091  * Returns: TRUE on success, FALSE on failure
2092  *
2093  * Setter for "Properties" property of a persistent group.
2094  */
2095 dbus_bool_t wpas_dbus_setter_persistent_group_properties(
2096 	const struct wpa_dbus_property_desc *property_desc,
2097 	DBusMessageIter *iter, DBusError *error, void *user_data)
2098 {
2099 	struct network_handler_args *net = user_data;
2100 	struct wpa_ssid *ssid = net->ssid;
2101 	DBusMessageIter	variant_iter;
2102 
2103 	/*
2104 	 * Leveraging the fact that persistent group object is still
2105 	 * represented in same manner as network within.
2106 	 */
2107 	dbus_message_iter_recurse(iter, &variant_iter);
2108 	return set_network_properties(net->wpa_s, ssid, &variant_iter, error);
2109 }
2110 
2111 
2112 /**
2113  * wpas_dbus_new_iface_add_persistent_group - Add a new configured
2114  *	persistent_group
2115  * @message: Pointer to incoming dbus message
2116  * @wpa_s: wpa_supplicant structure for a network interface
2117  * Returns: A dbus message containing the object path of the new
2118  * persistent group
2119  *
2120  * Handler function for "AddPersistentGroup" method call of a P2P Device
2121  * interface.
2122  */
2123 DBusMessage * wpas_dbus_handler_add_persistent_group(
2124 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2125 {
2126 	DBusMessage *reply = NULL;
2127 	DBusMessageIter	iter;
2128 	struct wpa_ssid *ssid = NULL;
2129 	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
2130 	DBusError error;
2131 
2132 	dbus_message_iter_init(message, &iter);
2133 
2134 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2135 	if (!wpa_s) {
2136 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2137 		goto err;
2138 	}
2139 
2140 	if (wpa_s->parent->dbus_new_path)
2141 		ssid = wpa_config_add_network(wpa_s->conf);
2142 	if (ssid == NULL) {
2143 		wpa_printf(MSG_ERROR,
2144 			   "dbus: %s: Cannot add new persistent group",
2145 			   __func__);
2146 		reply = wpas_dbus_error_unknown_error(
2147 			message,
2148 			"wpa_supplicant could not add a persistent group on this interface.");
2149 		goto err;
2150 	}
2151 
2152 	/* Mark the ssid as being a persistent group before the notification */
2153 	ssid->disabled = 2;
2154 	ssid->p2p_persistent_group = 1;
2155 	wpas_notify_persistent_group_added(wpa_s, ssid);
2156 
2157 	wpa_config_set_network_defaults(ssid);
2158 
2159 	dbus_error_init(&error);
2160 	if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
2161 		wpa_printf(MSG_DEBUG,
2162 			   "dbus: %s: Control interface could not set persistent group properties",
2163 			   __func__);
2164 		reply = wpas_dbus_reply_new_from_error(
2165 			message, &error, DBUS_ERROR_INVALID_ARGS,
2166 			"Failed to set network properties");
2167 		dbus_error_free(&error);
2168 		goto err;
2169 	}
2170 
2171 	/* Construct the object path for this network. */
2172 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2173 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%d",
2174 		    wpa_s->parent->dbus_new_path, ssid->id);
2175 
2176 	reply = dbus_message_new_method_return(message);
2177 	if (reply == NULL) {
2178 		reply = wpas_dbus_error_no_memory(message);
2179 		goto err;
2180 	}
2181 	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
2182 				      DBUS_TYPE_INVALID)) {
2183 		dbus_message_unref(reply);
2184 		reply = wpas_dbus_error_no_memory(message);
2185 		goto err;
2186 	}
2187 
2188 	return reply;
2189 
2190 err:
2191 	if (ssid) {
2192 		wpas_notify_persistent_group_removed(wpa_s, ssid);
2193 		wpa_config_remove_network(wpa_s->conf, ssid->id);
2194 	}
2195 	return reply;
2196 }
2197 
2198 
2199 /**
2200  * wpas_dbus_handler_remove_persistent_group - Remove a configured persistent
2201  *	group
2202  * @message: Pointer to incoming dbus message
2203  * @wpa_s: wpa_supplicant structure for a network interface
2204  * Returns: NULL on success or dbus error on failure
2205  *
2206  * Handler function for "RemovePersistentGroup" method call of a P2P Device
2207  * interface.
2208  */
2209 DBusMessage * wpas_dbus_handler_remove_persistent_group(
2210 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2211 {
2212 	DBusMessage *reply = NULL;
2213 	const char *op;
2214 	char *iface = NULL, *persistent_group_id;
2215 	int id;
2216 	struct wpa_ssid *ssid;
2217 
2218 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
2219 			      DBUS_TYPE_INVALID);
2220 
2221 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2222 	if (!wpa_s) {
2223 		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
2224 		goto out;
2225 	}
2226 
2227 	/*
2228 	 * Extract the network ID and ensure the network is actually a child of
2229 	 * this interface.
2230 	 */
2231 	iface = wpas_dbus_new_decompose_object_path(
2232 		op, WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART,
2233 		&persistent_group_id);
2234 	if (iface == NULL || persistent_group_id == NULL ||
2235 	    !wpa_s->parent->dbus_new_path ||
2236 	    os_strcmp(iface, wpa_s->parent->dbus_new_path) != 0) {
2237 		reply = wpas_dbus_error_invalid_args(message, op);
2238 		goto out;
2239 	}
2240 
2241 	id = strtoul(persistent_group_id, NULL, 10);
2242 	if (errno == EINVAL) {
2243 		reply = wpas_dbus_error_invalid_args(message, op);
2244 		goto out;
2245 	}
2246 
2247 	ssid = wpa_config_get_network(wpa_s->conf, id);
2248 	if (ssid == NULL) {
2249 		reply = wpas_dbus_error_persistent_group_unknown(message);
2250 		goto out;
2251 	}
2252 
2253 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2254 
2255 	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2256 		wpa_printf(MSG_ERROR,
2257 			   "dbus: %s: error occurred when removing persistent group %d",
2258 			   __func__, id);
2259 		reply = wpas_dbus_error_unknown_error(
2260 			message,
2261 			"error removing the specified persistent group on this interface.");
2262 		goto out;
2263 	}
2264 
2265 out:
2266 	os_free(iface);
2267 	return reply;
2268 }
2269 
2270 
2271 static void remove_persistent_group(struct wpa_supplicant *wpa_s,
2272 				    struct wpa_ssid *ssid)
2273 {
2274 	wpas_notify_persistent_group_removed(wpa_s, ssid);
2275 
2276 	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
2277 		wpa_printf(MSG_ERROR,
2278 			   "dbus: %s: error occurred when removing persistent group %d",
2279 			   __func__, ssid->id);
2280 		return;
2281 	}
2282 }
2283 
2284 
2285 /**
2286  * wpas_dbus_handler_remove_all_persistent_groups - Remove all configured
2287  * persistent groups
2288  * @message: Pointer to incoming dbus message
2289  * @wpa_s: wpa_supplicant structure for a network interface
2290  * Returns: NULL on success or dbus error on failure
2291  *
2292  * Handler function for "RemoveAllPersistentGroups" method call of a
2293  * P2P Device interface.
2294  */
2295 DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
2296 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2297 {
2298 	struct wpa_ssid *ssid, *next;
2299 	struct wpa_config *config;
2300 
2301 	wpa_s = wpa_s->global->p2p_init_wpa_s;
2302 	if (!wpa_s)
2303 		return wpas_dbus_error_no_p2p_mgmt_iface(message);
2304 
2305 	config = wpa_s->conf;
2306 	ssid = config->ssid;
2307 	while (ssid) {
2308 		next = ssid->next;
2309 		if (network_is_persistent_group(ssid))
2310 			remove_persistent_group(wpa_s, ssid);
2311 		ssid = next;
2312 	}
2313 	return NULL;
2314 }
2315 
2316 
2317 /*
2318  * Group object properties accessor methods
2319  */
2320 
2321 dbus_bool_t wpas_dbus_getter_p2p_group_members(
2322 	const struct wpa_dbus_property_desc *property_desc,
2323 	DBusMessageIter *iter, DBusError *error, void *user_data)
2324 {
2325 	struct wpa_supplicant *wpa_s = user_data;
2326 	struct wpa_ssid *ssid;
2327 	unsigned int num_members;
2328 	char **paths;
2329 	unsigned int i;
2330 	void *next = NULL;
2331 	const u8 *addr;
2332 	dbus_bool_t success = FALSE;
2333 
2334 	if (!wpa_s->parent->parent->dbus_new_path)
2335 		return FALSE;
2336 
2337 	/* Verify correct role for this property */
2338 	if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
2339 		return wpas_dbus_simple_array_property_getter(
2340 			iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
2341 	}
2342 
2343 	ssid = wpa_s->conf->ssid;
2344 	/* At present WPAS P2P_GO mode only applicable for p2p_go */
2345 	if (ssid->mode != WPAS_MODE_P2P_GO &&
2346 	    ssid->mode != WPAS_MODE_AP &&
2347 	    ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
2348 		return FALSE;
2349 
2350 	num_members = p2p_get_group_num_members(wpa_s->p2p_group);
2351 
2352 	paths = os_calloc(num_members, sizeof(char *));
2353 	if (!paths)
2354 		goto out_of_memory;
2355 
2356 	i = 0;
2357 	while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
2358 		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
2359 		if (!paths[i])
2360 			goto out_of_memory;
2361 		os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
2362 			    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
2363 			    "/" COMPACT_MACSTR,
2364 			    wpa_s->parent->parent->dbus_new_path,
2365 			    MAC2STR(addr));
2366 		i++;
2367 	}
2368 
2369 	success = wpas_dbus_simple_array_property_getter(iter,
2370 							 DBUS_TYPE_OBJECT_PATH,
2371 							 paths, num_members,
2372 							 error);
2373 
2374 	for (i = 0; i < num_members; i++)
2375 		os_free(paths[i]);
2376 	os_free(paths);
2377 	return success;
2378 
2379 out_of_memory:
2380 	dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
2381 	if (paths) {
2382 		for (i = 0; i < num_members; i++)
2383 			os_free(paths[i]);
2384 		os_free(paths);
2385 	}
2386 	return FALSE;
2387 }
2388 
2389 
2390 dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
2391 	const struct wpa_dbus_property_desc *property_desc,
2392 	DBusMessageIter *iter, DBusError *error, void *user_data)
2393 {
2394 	struct wpa_supplicant *wpa_s = user_data;
2395 
2396 	if (wpa_s->current_ssid == NULL)
2397 		return FALSE;
2398 	return wpas_dbus_simple_array_property_getter(
2399 		iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
2400 		wpa_s->current_ssid->ssid_len, error);
2401 }
2402 
2403 
2404 dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
2405 	const struct wpa_dbus_property_desc *property_desc,
2406 	DBusMessageIter *iter, DBusError *error, void *user_data)
2407 {
2408 	struct wpa_supplicant *wpa_s = user_data;
2409 	u8 role = wpas_get_p2p_role(wpa_s);
2410 	u8 *p_bssid;
2411 
2412 	if (role == WPAS_P2P_ROLE_CLIENT) {
2413 		if (wpa_s->current_ssid == NULL)
2414 			return FALSE;
2415 		p_bssid = wpa_s->current_ssid->bssid;
2416 	} else {
2417 		if (wpa_s->ap_iface == NULL)
2418 			return FALSE;
2419 		p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
2420 	}
2421 
2422 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2423 						      p_bssid, ETH_ALEN,
2424 						      error);
2425 }
2426 
2427 
2428 dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
2429 	const struct wpa_dbus_property_desc *property_desc,
2430 	DBusMessageIter *iter, DBusError *error, void *user_data)
2431 {
2432 	struct wpa_supplicant *wpa_s = user_data;
2433 	u16 op_freq;
2434 	u8 role = wpas_get_p2p_role(wpa_s);
2435 
2436 	if (role == WPAS_P2P_ROLE_CLIENT) {
2437 		if (wpa_s->go_params == NULL)
2438 			return FALSE;
2439 		op_freq = wpa_s->go_params->freq;
2440 	} else {
2441 		if (wpa_s->ap_iface == NULL)
2442 			return FALSE;
2443 		op_freq = wpa_s->ap_iface->freq;
2444 	}
2445 
2446 	return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
2447 						&op_freq, error);
2448 }
2449 
2450 
2451 dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
2452 	const struct wpa_dbus_property_desc *property_desc,
2453 	DBusMessageIter *iter, DBusError *error, void *user_data)
2454 {
2455 	struct wpa_supplicant *wpa_s = user_data;
2456 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2457 
2458 	if (ssid == NULL)
2459 		return FALSE;
2460 
2461 	return wpas_dbus_string_property_getter(iter, ssid->passphrase, error);
2462 }
2463 
2464 
2465 dbus_bool_t wpas_dbus_getter_p2p_group_psk(
2466 	const struct wpa_dbus_property_desc *property_desc,
2467 	DBusMessageIter *iter, DBusError *error, void *user_data)
2468 {
2469 	struct wpa_supplicant *wpa_s = user_data;
2470 	u8 *p_psk = NULL;
2471 	u8 psk_len = 0;
2472 	struct wpa_ssid *ssid = wpa_s->current_ssid;
2473 
2474 	if (ssid == NULL)
2475 		return FALSE;
2476 
2477 	if (ssid->psk_set) {
2478 		p_psk = ssid->psk;
2479 		psk_len = sizeof(ssid->psk);
2480 	}
2481 
2482 	return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
2483 						      p_psk, psk_len, error);
2484 }
2485 
2486 
2487 dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
2488 	const struct wpa_dbus_property_desc *property_desc,
2489 	DBusMessageIter *iter, DBusError *error, void *user_data)
2490 {
2491 	struct wpa_supplicant *wpa_s = user_data;
2492 	struct hostapd_data *hapd;
2493 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
2494 	unsigned int i, num_vendor_ext = 0;
2495 
2496 	os_memset(vendor_ext, 0, sizeof(vendor_ext));
2497 
2498 	/* Verify correct role for this property */
2499 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
2500 		if (wpa_s->ap_iface == NULL)
2501 			return FALSE;
2502 		hapd = wpa_s->ap_iface->bss[0];
2503 
2504 		/* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
2505 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2506 			if (hapd->conf->wps_vendor_ext[i] == NULL)
2507 				continue;
2508 			vendor_ext[num_vendor_ext++] =
2509 				hapd->conf->wps_vendor_ext[i];
2510 		}
2511 	}
2512 
2513 	/* Return vendor extensions or no data */
2514 	return wpas_dbus_simple_array_array_property_getter(iter,
2515 							    DBUS_TYPE_BYTE,
2516 							    vendor_ext,
2517 							    num_vendor_ext,
2518 							    error);
2519 }
2520 
2521 
2522 dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
2523 	const struct wpa_dbus_property_desc *property_desc,
2524 	DBusMessageIter *iter, DBusError *error, void *user_data)
2525 {
2526 	struct wpa_supplicant *wpa_s = user_data;
2527 	DBusMessageIter variant_iter, iter_dict, array_iter, sub;
2528 	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
2529 	unsigned int i;
2530 	struct hostapd_data *hapd = NULL;
2531 
2532 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO &&
2533 	    wpa_s->ap_iface != NULL)
2534 		hapd = wpa_s->ap_iface->bss[0];
2535 	else
2536 		return FALSE;
2537 
2538 	dbus_message_iter_recurse(iter, &variant_iter);
2539 	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
2540 		return FALSE;
2541 
2542 	/*
2543 	 * This is supposed to be array of bytearrays (aay), but the earlier
2544 	 * implementation used a dict with "WPSVendorExtensions" as the key in
2545 	 * this setter function which does not match the format used by the
2546 	 * getter function. For backwards compatibility, allow both formats to
2547 	 * be used in the setter.
2548 	 */
2549 	if (dbus_message_iter_get_element_type(&variant_iter) ==
2550 	    DBUS_TYPE_ARRAY) {
2551 		/* This is the proper format matching the getter */
2552 		struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
2553 
2554 		dbus_message_iter_recurse(&variant_iter, &array_iter);
2555 
2556 		if (dbus_message_iter_get_arg_type(&array_iter) !=
2557 		    DBUS_TYPE_ARRAY ||
2558 		    dbus_message_iter_get_element_type(&array_iter) !=
2559 		    DBUS_TYPE_BYTE) {
2560 			wpa_printf(MSG_DEBUG,
2561 				   "dbus: Not an array of array of bytes");
2562 			return FALSE;
2563 		}
2564 
2565 		i = 0;
2566 		os_memset(vals, 0, sizeof(vals));
2567 
2568 		while (dbus_message_iter_get_arg_type(&array_iter) ==
2569 		       DBUS_TYPE_ARRAY) {
2570 			char *val;
2571 			int len;
2572 
2573 			if (i == MAX_WPS_VENDOR_EXTENSIONS) {
2574 				wpa_printf(MSG_DEBUG,
2575 					   "dbus: Too many WPSVendorExtensions values");
2576 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2577 				break;
2578 			}
2579 
2580 			dbus_message_iter_recurse(&array_iter, &sub);
2581 			dbus_message_iter_get_fixed_array(&sub, &val, &len);
2582 			wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
2583 				    val, len);
2584 			vals[i] = wpabuf_alloc_copy(val, len);
2585 			if (vals[i] == NULL) {
2586 				i = MAX_WPS_VENDOR_EXTENSIONS + 1;
2587 				break;
2588 			}
2589 			i++;
2590 			dbus_message_iter_next(&array_iter);
2591 		}
2592 
2593 		if (i > MAX_WPS_VENDOR_EXTENSIONS) {
2594 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
2595 				wpabuf_free(vals[i]);
2596 			return FALSE;
2597 		}
2598 
2599 		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2600 			wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2601 			hapd->conf->wps_vendor_ext[i] = vals[i];
2602 		}
2603 
2604 		hostapd_update_wps(hapd);
2605 
2606 		return TRUE;
2607 	}
2608 
2609 	if (dbus_message_iter_get_element_type(&variant_iter) !=
2610 	    DBUS_TYPE_DICT_ENTRY)
2611 		return FALSE;
2612 
2613 	wpa_printf(MSG_DEBUG,
2614 		   "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
2615 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
2616 		return FALSE;
2617 
2618 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2619 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
2620 			dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2621 					     "invalid message format");
2622 			return FALSE;
2623 		}
2624 
2625 		if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
2626 			if (entry.type != DBUS_TYPE_ARRAY ||
2627 			    entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
2628 			    entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
2629 				goto error;
2630 
2631 			for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2632 				wpabuf_free(hapd->conf->wps_vendor_ext[i]);
2633 				if (i < entry.array_len) {
2634 					hapd->conf->wps_vendor_ext[i] =
2635 						entry.binarray_value[i];
2636 					entry.binarray_value[i] = NULL;
2637 				} else
2638 					hapd->conf->wps_vendor_ext[i] = NULL;
2639 			}
2640 
2641 			hostapd_update_wps(hapd);
2642 		} else
2643 			goto error;
2644 
2645 		wpa_dbus_dict_entry_clear(&entry);
2646 	}
2647 
2648 	return TRUE;
2649 
2650 error:
2651 	wpa_dbus_dict_entry_clear(&entry);
2652 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
2653 			     "invalid message format");
2654 	return FALSE;
2655 }
2656 
2657 
2658 DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
2659 						struct wpa_supplicant *wpa_s)
2660 {
2661 	DBusMessageIter iter_dict;
2662 	DBusMessage *reply = NULL;
2663 	DBusMessageIter iter;
2664 	struct wpa_dbus_dict_entry entry;
2665 	int upnp = 0;
2666 	int bonjour = 0;
2667 	char *service = NULL;
2668 	struct wpabuf *query = NULL;
2669 	struct wpabuf *resp = NULL;
2670 	u8 version = 0;
2671 
2672 	dbus_message_iter_init(message, &iter);
2673 
2674 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2675 		goto error;
2676 
2677 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2678 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2679 			goto error;
2680 
2681 		if (os_strcmp(entry.key, "service_type") == 0 &&
2682 		    entry.type == DBUS_TYPE_STRING) {
2683 			if (os_strcmp(entry.str_value, "upnp") == 0)
2684 				upnp = 1;
2685 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2686 				bonjour = 1;
2687 			else
2688 				goto error_clear;
2689 		} else if (os_strcmp(entry.key, "version") == 0 &&
2690 			   entry.type == DBUS_TYPE_INT32) {
2691 			version = entry.uint32_value;
2692 		} else if (os_strcmp(entry.key, "service") == 0 &&
2693 			   entry.type == DBUS_TYPE_STRING) {
2694 			os_free(service);
2695 			service = os_strdup(entry.str_value);
2696 		} else if (os_strcmp(entry.key, "query") == 0) {
2697 			if (entry.type != DBUS_TYPE_ARRAY ||
2698 			    entry.array_type != DBUS_TYPE_BYTE)
2699 				goto error_clear;
2700 			query = wpabuf_alloc_copy(
2701 				entry.bytearray_value,
2702 				entry.array_len);
2703 		} else if (os_strcmp(entry.key, "response") == 0) {
2704 			if (entry.type != DBUS_TYPE_ARRAY ||
2705 			    entry.array_type != DBUS_TYPE_BYTE)
2706 				goto error_clear;
2707 			resp = wpabuf_alloc_copy(entry.bytearray_value,
2708 						 entry.array_len);
2709 		}
2710 		wpa_dbus_dict_entry_clear(&entry);
2711 	}
2712 
2713 	if (upnp == 1) {
2714 		if (version <= 0 || service == NULL)
2715 			goto error;
2716 
2717 		if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
2718 			goto error;
2719 
2720 	} else if (bonjour == 1) {
2721 		if (query == NULL || resp == NULL)
2722 			goto error;
2723 
2724 		if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
2725 			goto error;
2726 		query = NULL;
2727 		resp = NULL;
2728 	} else
2729 		goto error;
2730 
2731 	os_free(service);
2732 	return reply;
2733 error_clear:
2734 	wpa_dbus_dict_entry_clear(&entry);
2735 error:
2736 	os_free(service);
2737 	wpabuf_free(query);
2738 	wpabuf_free(resp);
2739 	return wpas_dbus_error_invalid_args(message, NULL);
2740 }
2741 
2742 
2743 DBusMessage * wpas_dbus_handler_p2p_delete_service(
2744 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2745 {
2746 	DBusMessageIter iter_dict;
2747 	DBusMessage *reply = NULL;
2748 	DBusMessageIter iter;
2749 	struct wpa_dbus_dict_entry entry;
2750 	int upnp = 0;
2751 	int bonjour = 0;
2752 	int ret = 0;
2753 	char *service = NULL;
2754 	struct wpabuf *query = NULL;
2755 	u8 version = 0;
2756 
2757 	dbus_message_iter_init(message, &iter);
2758 
2759 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2760 		goto error;
2761 
2762 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2763 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2764 			goto error;
2765 
2766 		if (os_strcmp(entry.key, "service_type") == 0 &&
2767 		    entry.type == DBUS_TYPE_STRING) {
2768 			if (os_strcmp(entry.str_value, "upnp") == 0)
2769 				upnp = 1;
2770 			else if (os_strcmp(entry.str_value, "bonjour") == 0)
2771 				bonjour = 1;
2772 			else
2773 				goto error_clear;
2774 		} else if (os_strcmp(entry.key, "version") == 0 &&
2775 			   entry.type == DBUS_TYPE_INT32) {
2776 			version = entry.uint32_value;
2777 		} else if (os_strcmp(entry.key, "service") == 0 &&
2778 			   entry.type == DBUS_TYPE_STRING) {
2779 			os_free(service);
2780 			service = os_strdup(entry.str_value);
2781 		} else if (os_strcmp(entry.key, "query") == 0) {
2782 			if (entry.type != DBUS_TYPE_ARRAY ||
2783 			    entry.array_type != DBUS_TYPE_BYTE)
2784 				goto error_clear;
2785 			wpabuf_free(query);
2786 			query = wpabuf_alloc_copy(entry.bytearray_value,
2787 						  entry.array_len);
2788 		} else {
2789 			goto error_clear;
2790 		}
2791 
2792 		wpa_dbus_dict_entry_clear(&entry);
2793 	}
2794 	if (upnp == 1) {
2795 		if (version <= 0 || service == NULL)
2796 			goto error;
2797 
2798 		ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
2799 		if (ret != 0)
2800 			goto error;
2801 	} else if (bonjour == 1) {
2802 		if (query == NULL)
2803 			goto error;
2804 
2805 		ret = wpas_p2p_service_del_bonjour(wpa_s, query);
2806 		if (ret != 0)
2807 			goto error;
2808 	} else
2809 		goto error;
2810 
2811 	wpabuf_free(query);
2812 	os_free(service);
2813 	return reply;
2814 error_clear:
2815 	wpa_dbus_dict_entry_clear(&entry);
2816 error:
2817 	wpabuf_free(query);
2818 	os_free(service);
2819 	return wpas_dbus_error_invalid_args(message, NULL);
2820 }
2821 
2822 
2823 DBusMessage * wpas_dbus_handler_p2p_flush_service(DBusMessage *message,
2824 						  struct wpa_supplicant *wpa_s)
2825 {
2826 	wpas_p2p_service_flush(wpa_s);
2827 	return NULL;
2828 }
2829 
2830 
2831 DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
2832 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2833 {
2834 	DBusMessageIter iter_dict;
2835 	DBusMessage *reply = NULL;
2836 	DBusMessageIter iter;
2837 	struct wpa_dbus_dict_entry entry;
2838 	int upnp = 0;
2839 	char *service = NULL;
2840 	char *peer_object_path = NULL;
2841 	struct wpabuf *tlv = NULL;
2842 	u8 version = 0;
2843 	u64 ref = 0;
2844 	u8 addr_buf[ETH_ALEN], *addr;
2845 
2846 	dbus_message_iter_init(message, &iter);
2847 
2848 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2849 		goto error;
2850 
2851 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2852 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2853 			goto error;
2854 		if (os_strcmp(entry.key, "peer_object") == 0 &&
2855 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2856 			peer_object_path = os_strdup(entry.str_value);
2857 		} else if (os_strcmp(entry.key, "service_type") == 0 &&
2858 			   entry.type == DBUS_TYPE_STRING) {
2859 			if (os_strcmp(entry.str_value, "upnp") == 0)
2860 				upnp = 1;
2861 			else
2862 				goto error_clear;
2863 		} else if (os_strcmp(entry.key, "version") == 0 &&
2864 			   entry.type == DBUS_TYPE_INT32) {
2865 			version = entry.uint32_value;
2866 		} else if (os_strcmp(entry.key, "service") == 0 &&
2867 			   entry.type == DBUS_TYPE_STRING) {
2868 			service = os_strdup(entry.str_value);
2869 		} else if (os_strcmp(entry.key, "tlv") == 0) {
2870 			if (entry.type != DBUS_TYPE_ARRAY ||
2871 			    entry.array_type != DBUS_TYPE_BYTE)
2872 				goto error_clear;
2873 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2874 						entry.array_len);
2875 		} else
2876 			goto error_clear;
2877 
2878 		wpa_dbus_dict_entry_clear(&entry);
2879 	}
2880 
2881 	if (!peer_object_path) {
2882 		addr = NULL;
2883 	} else {
2884 		if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
2885 		    !p2p_peer_known(wpa_s->global->p2p, addr_buf))
2886 			goto error;
2887 
2888 		addr = addr_buf;
2889 	}
2890 
2891 	if (upnp == 1) {
2892 		if (version <= 0 || service == NULL)
2893 			goto error;
2894 
2895 		ref = wpas_p2p_sd_request_upnp(wpa_s, addr, version, service);
2896 	} else {
2897 		if (tlv == NULL)
2898 			goto error;
2899 		ref = wpas_p2p_sd_request(wpa_s, addr, tlv);
2900 		wpabuf_free(tlv);
2901 	}
2902 
2903 	if (ref != 0) {
2904 		reply = dbus_message_new_method_return(message);
2905 		dbus_message_append_args(reply, DBUS_TYPE_UINT64,
2906 					 &ref, DBUS_TYPE_INVALID);
2907 	} else {
2908 		reply = wpas_dbus_error_unknown_error(
2909 			message, "Unable to send SD request");
2910 	}
2911 out:
2912 	os_free(service);
2913 	os_free(peer_object_path);
2914 	return reply;
2915 error_clear:
2916 	wpa_dbus_dict_entry_clear(&entry);
2917 error:
2918 	if (tlv)
2919 		wpabuf_free(tlv);
2920 	reply = wpas_dbus_error_invalid_args(message, NULL);
2921 	goto out;
2922 }
2923 
2924 
2925 DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
2926 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2927 {
2928 	DBusMessageIter iter_dict;
2929 	DBusMessage *reply = NULL;
2930 	DBusMessageIter iter;
2931 	struct wpa_dbus_dict_entry entry;
2932 	char *peer_object_path = NULL;
2933 	struct wpabuf *tlv = NULL;
2934 	int freq = 0;
2935 	int dlg_tok = 0;
2936 	u8 addr[ETH_ALEN];
2937 
2938 	dbus_message_iter_init(message, &iter);
2939 
2940 	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
2941 		goto error;
2942 
2943 	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
2944 		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
2945 			goto error;
2946 
2947 		if (os_strcmp(entry.key, "peer_object") == 0 &&
2948 		    entry.type == DBUS_TYPE_OBJECT_PATH) {
2949 			peer_object_path = os_strdup(entry.str_value);
2950 		} else if (os_strcmp(entry.key, "frequency") == 0 &&
2951 			   entry.type == DBUS_TYPE_INT32) {
2952 			freq = entry.uint32_value;
2953 		} else if (os_strcmp(entry.key, "dialog_token") == 0 &&
2954 			   (entry.type == DBUS_TYPE_UINT32 ||
2955 			    entry.type == DBUS_TYPE_INT32)) {
2956 			dlg_tok = entry.uint32_value;
2957 		} else if (os_strcmp(entry.key, "tlvs") == 0) {
2958 			if (entry.type != DBUS_TYPE_ARRAY ||
2959 			    entry.array_type != DBUS_TYPE_BYTE)
2960 				goto error_clear;
2961 			tlv = wpabuf_alloc_copy(entry.bytearray_value,
2962 						entry.array_len);
2963 		} else
2964 			goto error_clear;
2965 
2966 		wpa_dbus_dict_entry_clear(&entry);
2967 	}
2968 	if (parse_peer_object_path(peer_object_path, addr) < 0 ||
2969 	    !p2p_peer_known(wpa_s->global->p2p, addr) ||
2970 	    tlv == NULL)
2971 		goto error;
2972 
2973 	wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
2974 	wpabuf_free(tlv);
2975 out:
2976 	os_free(peer_object_path);
2977 	return reply;
2978 error_clear:
2979 	wpa_dbus_dict_entry_clear(&entry);
2980 error:
2981 	reply = wpas_dbus_error_invalid_args(message, NULL);
2982 	goto out;
2983 }
2984 
2985 
2986 DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
2987 	DBusMessage *message, struct wpa_supplicant *wpa_s)
2988 {
2989 	DBusMessageIter iter;
2990 	u64 req = 0;
2991 
2992 	dbus_message_iter_init(message, &iter);
2993 	dbus_message_iter_get_basic(&iter, &req);
2994 
2995 	if (req == 0)
2996 		goto error;
2997 
2998 	if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
2999 		goto error;
3000 
3001 	return NULL;
3002 error:
3003 	return wpas_dbus_error_invalid_args(message, NULL);
3004 }
3005 
3006 
3007 DBusMessage * wpas_dbus_handler_p2p_service_update(
3008 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3009 {
3010 	wpas_p2p_sd_service_update(wpa_s);
3011 	return NULL;
3012 }
3013 
3014 
3015 DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
3016 	DBusMessage *message, struct wpa_supplicant *wpa_s)
3017 {
3018 	DBusMessageIter iter;
3019 	int ext = 0;
3020 
3021 	dbus_message_iter_init(message, &iter);
3022 	dbus_message_iter_get_basic(&iter, &ext);
3023 
3024 	wpa_s->p2p_sd_over_ctrl_iface = ext;
3025 
3026 	return NULL;
3027 
3028 }
3029 
3030 
3031 #ifdef CONFIG_WIFI_DISPLAY
3032 
3033 dbus_bool_t wpas_dbus_getter_global_wfd_ies(
3034 	const struct wpa_dbus_property_desc *property_desc,
3035 	DBusMessageIter *iter, DBusError *error, void *user_data)
3036 {
3037 	struct wpa_global *global = user_data;
3038 	struct wpabuf *ie;
3039 	dbus_bool_t ret;
3040 
3041 	ie = wifi_display_get_wfd_ie(global);
3042 	if (ie == NULL)
3043 		return wpas_dbus_simple_array_property_getter(iter,
3044 							      DBUS_TYPE_BYTE,
3045 							      NULL, 0, error);
3046 
3047 	ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
3048 						     wpabuf_head(ie),
3049 						     wpabuf_len(ie), error);
3050 	wpabuf_free(ie);
3051 
3052 	return ret;
3053 }
3054 
3055 
3056 dbus_bool_t wpas_dbus_setter_global_wfd_ies(
3057 	const struct wpa_dbus_property_desc *property_desc,
3058 	DBusMessageIter *iter, DBusError *error, void *user_data)
3059 {
3060 	struct wpa_global *global = user_data;
3061 	DBusMessageIter variant, array;
3062 	struct wpabuf *ie = NULL;
3063 	const u8 *data;
3064 	int len;
3065 
3066 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
3067 		goto err;
3068 
3069 	dbus_message_iter_recurse(iter, &variant);
3070 	if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
3071 		goto err;
3072 
3073 	dbus_message_iter_recurse(&variant, &array);
3074 	dbus_message_iter_get_fixed_array(&array, &data, &len);
3075 	if (len == 0) {
3076 		wifi_display_enable(global, 0);
3077 		wifi_display_deinit(global);
3078 
3079 		return TRUE;
3080 	}
3081 
3082 	ie = wpabuf_alloc(len);
3083 	if (ie == NULL)
3084 		goto err;
3085 
3086 	wpabuf_put_data(ie, data, len);
3087 	if (wifi_display_subelem_set_from_ies(global, ie) != 0)
3088 		goto err;
3089 
3090 	if (global->wifi_display == 0)
3091 		wifi_display_enable(global, 1);
3092 
3093 	wpabuf_free(ie);
3094 
3095 	return TRUE;
3096 err:
3097 	wpabuf_free(ie);
3098 
3099 	dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
3100 			     "invalid message format");
3101 	return FALSE;
3102 }
3103 
3104 #endif /* CONFIG_WIFI_DISPLAY */
3105