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